From 92bdb5567222ef3945b259320004a6eac99545d3 Mon Sep 17 00:00:00 2001 From: Aaron Giles Date: Thu, 5 Feb 2015 00:18:10 -0800 Subject: [PATCH] JPEGView 3.3 for Macintosh These are the sources for the final official release of JPEGView for the Mac, back in 1994. --- Headers/AppleEventUtils.h | 1 + Headers/AppleMenu.h | 1 + Headers/BMP.h | 1 + Headers/Bottlenecks.h | 1 + Headers/ColorsMenu.h | 1 + Headers/ColorsWindow.h | 1 + Headers/CommentsWindow.h | 1 + Headers/CompressedResource.h | 1 + Headers/CoreEventHandlers.h | 1 + Headers/CustomCopyBits.h | 1 + Headers/DialogUtils.h | 1 + Headers/EditMenu.h | 1 + Headers/EventHandlers.h | 1 + Headers/EventUtils.h | 1 + Headers/FileMenu.h | 1 + Headers/FloatingWindows.h | 1 + Headers/GIF.h | 1 + Headers/GeneralMenus.h | 1 + Headers/HelpMenu.h | 1 + Headers/ImageUtils.h | 1 + Headers/JPEG.h | 1 + Headers/JPEGNoQuickTime.h | 1 + Headers/JPEGView.h | 1 + Headers/JPEGView.h.o | Bin 0 -> 22 bytes Headers/JPEGView.r.h | 1 + Headers/JPEGViewEventHandlers.h | 1 + Headers/JPEGViewGlobals.h | 1 + Headers/JPEGViewPlugIn.h | 1 + Headers/JPEGViewTypes.h | 1 + Headers/MW.Header.68k | Bin 0 -> 392981 bytes Headers/MW.Header.PPC | Bin 0 -> 389077 bytes Headers/MarchingAnts.h | 1 + Headers/MemoryUtils.h | 1 + Headers/MercutioAPI.h | 1 + Headers/MiscellaneousUtils.h | 1 + Headers/MonitorUtils.h | 1 + Headers/PICT.h | 1 + Headers/PNTG.h | 1 + Headers/Preferences.h | 1 + Headers/ProgressProcs.h | 1 + Headers/QDxDispatchPatch.h | 1 + Headers/Quantize.h | 1 + Headers/QuickDrawUtils.h | 1 + Headers/RequiredEventHandlers.h | 1 + Headers/SCRN.h | 1 + Headers/SaveOpen.h | 1 + Headers/SendAppleEvents.h | 1 + Headers/SlideControlsWindow.h | 1 + Headers/SlideShow.h | 1 + Headers/SlideShowOptions.h | 1 + Headers/StandardFolder.h | 1 + Headers/StatisticsWindow.h | 1 + Headers/TIFF.h | 1 + Headers/ViewMenu.h | 1 + Headers/WindowMenu.h | 1 + Headers/WindowUtils.h | 1 + Headers/cApplication.h | 1 + Headers/cDocument.h | 1 + Headers/cDrawingArea.h | 1 + Headers/cFile.h | 1 + Headers/cImage.h | 1 + Headers/cPixelMap.h | 1 + Headers/cSelection.h | 1 + Headers/cWindow.h | 1 + Headers/jconfig.h | 1 + Headers/jerror.h | 1 + Headers/jmorecfg.h | 1 + Headers/jpeglib.h | 1 + Headers/jversion.h | 1 + Independent JPEG Group/Changed/jconfig.h | 1 + Independent JPEG Group/Changed/jdcolor.c | 1 + Independent JPEG Group/Changed/jmorecfg.h | 1 + Independent JPEG Group/JPEGLib.o | Bin 0 -> 74326 bytes Independent JPEG Group/JPEGLib.xcoff | Bin 0 -> 135538 bytes Independent JPEG Group/JPEGLib.µ | Bin 0 -> 141949 bytes Independent JPEG Group/Makefile.TXT | 1 + Independent JPEG Group/README.TXT | 1 + Independent JPEG Group/ansi2knr.1 | 1 + Independent JPEG Group/ansi2knr.c | 1 + Independent JPEG Group/cderror.h | 1 + Independent JPEG Group/cdjpeg.h | 1 + Independent JPEG Group/change.log | 1 + Independent JPEG Group/cjpeg.1 | 1 + Independent JPEG Group/cjpeg.c | 1 + Independent JPEG Group/ckconfig.c | 1 + Independent JPEG Group/coderules.doc | 1 + Independent JPEG Group/configure_.TXT | 1 + Independent JPEG Group/djpeg.1 | 1 + Independent JPEG Group/djpeg.c | 1 + Independent JPEG Group/example.c | 1 + Independent JPEG Group/filelist.doc | 1 + Independent JPEG Group/install.doc | 1 + Independent JPEG Group/jcapi.c | 1 + Independent JPEG Group/jccoefct.c | 1 + Independent JPEG Group/jccolor.c | 1 + Independent JPEG Group/jcdctmgr.c | 1 + Independent JPEG Group/jchuff.c | 1 + Independent JPEG Group/jcmainct.c | 1 + Independent JPEG Group/jcmarker.c | 1 + Independent JPEG Group/jcmaster.c | 1 + Independent JPEG Group/jcomapi.c | 1 + Independent JPEG Group/jconfig.auto | 1 + Independent JPEG Group/jconfig.bcc | 1 + Independent JPEG Group/jconfig.doc | 1 + Independent JPEG Group/jconfig.h | 1 + Independent JPEG Group/jconfig.manx | 1 + Independent JPEG Group/jconfig.mc6 | 1 + Independent JPEG Group/jconfig.sas | 1 + Independent JPEG Group/jconfig.st | 1 + Independent JPEG Group/jconfig.vms | 1 + Independent JPEG Group/jcparam.c | 1 + Independent JPEG Group/jcprepct.c | 1 + Independent JPEG Group/jcsample.c | 1 + Independent JPEG Group/jdapi.c | 1 + Independent JPEG Group/jdatadst.c | 1 + Independent JPEG Group/jdatasrc.c | 1 + Independent JPEG Group/jdcoefct.c | 1 + Independent JPEG Group/jdcolor.c | 1 + Independent JPEG Group/jdct.h | 1 + Independent JPEG Group/jddctmgr.c | 1 + Independent JPEG Group/jdhuff.c | 1 + Independent JPEG Group/jdmainct.c | 1 + Independent JPEG Group/jdmarker.c | 1 + Independent JPEG Group/jdmaster.c | 1 + Independent JPEG Group/jdpostct.c | 1 + Independent JPEG Group/jdsample.c | 1 + Independent JPEG Group/jerror.c | 1 + Independent JPEG Group/jerror.h | 1 + Independent JPEG Group/jfdctllm.c | 1 + Independent JPEG Group/jidctllm.c | 1 + Independent JPEG Group/jidctred.c | 1 + Independent JPEG Group/jinclude.h | 1 + Independent JPEG Group/jmemansi.c | 1 + Independent JPEG Group/jmemdos.c | 1 + Independent JPEG Group/jmemdosa.asm | 1 + Independent JPEG Group/jmemmgr.c | 1 + Independent JPEG Group/jmemname.c | 1 + Independent JPEG Group/jmemnobs.c | 1 + Independent JPEG Group/jmemsys.h | 1 + Independent JPEG Group/jmorecfg.h | 1 + Independent JPEG Group/jpegint.h | 1 + Independent JPEG Group/jpeglib.h | 1 + Independent JPEG Group/jquant1.c | 1 + Independent JPEG Group/jquant2.c | 1 + Independent JPEG Group/jutils.c | 1 + Independent JPEG Group/jversion.h | 1 + Independent JPEG Group/libjpeg.doc | 1 + Independent JPEG Group/makcjpeg.st | 1 + Independent JPEG Group/makdjpeg.st | 1 + Independent JPEG Group/makefile.ansi | 1 + Independent JPEG Group/makefile.auto | 1 + Independent JPEG Group/makefile.bcc | 1 + Independent JPEG Group/makefile.manx | 1 + Independent JPEG Group/makefile.mc6 | 1 + Independent JPEG Group/makefile.mms | 1 + Independent JPEG Group/makefile.sas | 1 + Independent JPEG Group/makefile.unix | 1 + Independent JPEG Group/makefile.vms | 1 + Independent JPEG Group/makljpeg.st | 1 + Independent JPEG Group/makvms.opt | 1 + Independent JPEG Group/rdgif.c | 1 + Independent JPEG Group/rdppm.c | 1 + Independent JPEG Group/rdtarga.c | 1 + Independent JPEG Group/structure.doc | 1 + Independent JPEG Group/testimg.jpg | Bin 0 -> 4374 bytes Independent JPEG Group/testorig.jpg | Bin 0 -> 4375 bytes Independent JPEG Group/usage.doc | 1 + Independent JPEG Group/wrgif.c | 1 + Independent JPEG Group/wrppm.c | 1 + Infinity Windoid 2_6/Infinity Windoid.makeout | 1 + Infinity Windoid 2_6/InfinityWDEF.pef | Bin 0 -> 11328 bytes Infinity Windoid 2_6/InfinityWDEF.r | 1 + Infinity Windoid 2_6/Makefile.TXT | 1 + Infinity Windoid 2_6/WindoidDefines.h | 1 + Infinity Windoid 2_6/obj/InfinityWDEF.xcoff | Bin 0 -> 58525 bytes JFIF Preview/JFIFPreview.c | 1 + JFIF Preview/JFIFPreview.fat.r | 1 + JFIF Preview/JFIFPreview.r | 1 + JFIF Preview/Makefile.TXT | 1 + JFIF Preview/obj/InfinityWDEF.xcoff | Bin 0 -> 59593 bytes JFIF Preview/obj/JFIFPreview.c.o | Bin 0 -> 4048 bytes JFIF Preview/obj/JFIFPreview.o | Bin 0 -> 10795 bytes JPEGView 3 3 docs.pdf | Bin 0 -> 623286 bytes JPEGView 3_3 ƒ/JPEGView | Bin 0 -> 360560 bytes JPEGView 3_3 ƒ/JPEGView 3.3 Blurb | 1 + JPEGView 3_3 ƒ/Parrots JPEG.JPG | Bin 0 -> 30073 bytes JPEGView 3_3 ƒ/Possible Conflicts | 1 + JPEGView 3_3 ƒ/Read Me 3.3! | 1 + JPEGView Read Me | 1 + Libraries/JPEGLib.o | Bin 0 -> 74326 bytes Libraries/JPEGLib.xcoff | Bin 0 -> 135538 bytes Make Resources.TXT | 1 + Makefile.TXT | 1 + New in JPEGView 3.3 | 1 + Pictures/Atlas Rocket.PCT | Bin 0 -> 50952 bytes Pictures/Earth Color.PCT | Bin 0 -> 87960 bytes Pictures/Eclipse.PCT | Bin 0 -> 28532 bytes Pictures/Escher-Snakes.PCT | Bin 0 -> 90242 bytes Pictures/Hubble Deployment.PCT | Bin 0 -> 61008 bytes Pictures/JPEGView About.PCT | Bin 0 -> 80032 bytes Pictures/PacMan.PCT | Bin 0 -> 51966 bytes Pictures/Sarah Bernhardt.PCT | Bin 0 -> 98352 bytes Pictures/Star Wars-Death Star.PCT | Bin 0 -> 65318 bytes Pictures/Yellow_Purple.PCT | Bin 0 -> 94688 bytes Read Me!.TXT | 1 + Resources/DialogHelpResources.r | 1 + Resources/DialogResources.r | 1 + Resources/GeneralHelpResources.r | 1 + Resources/GeneralResources.r | 1 + Resources/Help Text/01.Overview | 1 + Resources/Help Text/02.Viewing Images | 1 + Resources/Help Text/03.Floating Windows | 1 + Resources/Help Text/04.Special Effects | 1 + Resources/Help Text/05.Colors & Reduction | 1 + Resources/Help Text/06.Saving Images | 1 + Resources/Help Text/07.Slide Show | 1 + Resources/Help Text/08.Preferences Settings | 1 + Resources/Help Text/09.File Formats | Bin 0 -> 9329 bytes Resources/Help Text/10.Scripting JPEGView | 1 + Resources/Help Text/11.General JPEG Q&A | 1 + Resources/Help Text/12.JPEGView Q&A | 1 + Resources/Help Text/13.Hints And Tips | 1 + Resources/Help Text/14.Contacting the Author | 1 + Resources/Help Text/15.Acknowledgements | 1 + Resources/Help Text/16.Program History | 1 + Resources/Help Text/Technical Information.TXT | 1 + Resources/MenuHelpResources.r | 1 + Resources/MenuResources.r | 1 + Resources/PowerPCResources.r | 1 + Resources/aeteResource.r | 1 + Source/68020/CopyFastScaledFrom32.a | 1 + Source/68020/CopyReallyFastScaledFrom32.a | 1 + Source/68020/CopyScaledFrom32.a | 1 + Source/68020/CopyTo32.a | 1 + Source/68020/CopyUnscaledFrom32.a | 1 + Source/68020/CustomCopyBits.a | 1 + Source/68020/DecodeDummyRow.a | 1 + Source/68020/DecodeRow.a | 1 + Source/68020/DitherCopyTo16Even.a | 1 + Source/68020/DitherCopyTo16Odd.a | 1 + Source/68020/DitherCopyTo8Even.a | 1 + Source/68020/DitherCopyTo8Odd.a | 1 + Source/68020/FillHistogram16.a | 1 + Source/68020/FillHistogram32.a | 1 + Source/68020/GIF.a | 1 + Source/68020/InitRegion.a | 1 + Source/68020/QDxDispatchPatch.a | 1 + Source/68020/Quantize.a | 1 + Source/68020/UpdateRegion.a | 1 + Source/C/AppleEventUtils.c | 1 + Source/C/AppleMenu.c | 1 + Source/C/BMP.c | 1 + Source/C/Bottlenecks.c | 1 + Source/C/ColorsMenu.c | 1 + Source/C/ColorsWindow.c | 1 + Source/C/CommentsWindow.c | 1 + Source/C/CompressedResource.c | 1 + Source/C/CopyFastScaledFrom32.c | 1 + Source/C/CopyFastScaledFrom32.c copy | 1 + Source/C/CopyReallyFastScaledFrom32.c | 1 + Source/C/CopyScaledFrom32.c | 1 + Source/C/CopyScaledFrom32.c.float | 1 + Source/C/CopyTo32.c | 1 + Source/C/CopyUnscaledFrom32.c | 1 + Source/C/CoreEventHandlers.c | 1 + Source/C/CustomCopyBits.c | 1 + Source/C/DecodeDummyRow.c | 1 + Source/C/DecodeRow.c | 1 + Source/C/DialogUtils.c | 1 + Source/C/DitherCopyTo16Even.c | 1 + Source/C/DitherCopyTo16Odd.c | 1 + Source/C/DitherCopyTo8Even.c | 1 + Source/C/DitherCopyTo8Odd.c | 1 + Source/C/EditMenu.c | 1 + Source/C/EventHandlers.c | 1 + Source/C/EventUtils.c | 1 + Source/C/FileMenu.c | 1 + Source/C/FillHistogram16.c | 1 + Source/C/FillHistogram32.c | 1 + Source/C/FloatingWindows.c | 1 + Source/C/GIF.c | 1 + Source/C/GeneralMenus.c | 1 + Source/C/HelpMenu.c | 1 + Source/C/IJGJPEG.c | 1 + Source/C/ImageUtils.c | 1 + Source/C/InitRegion.c | 1 + Source/C/JPEG.c | 1 + Source/C/JPEGNoQuickTime.c | 1 + Source/C/JPEGView.c | 1 + Source/C/JPEGViewEventHandlers.c | 1 + Source/C/JPEGViewGlobals.c | 1 + Source/C/MarchingAnts.c | 1 + Source/C/MemoryUtils.c | 1 + Source/C/MercutioAPI.c | 1 + Source/C/MiscellaneousUtils.c | 1 + Source/C/MonitorUtils.c | 1 + Source/C/PICT.c | 1 + Source/C/PNTG.c | 1 + Source/C/PowerPCStub.c | 1 + Source/C/Preferences.c | 1 + Source/C/ProgressProcs.c | 1 + Source/C/QDxDispatchPatch.c | 1 + Source/C/Quantize.c | 1 + Source/C/QuickDrawUtils.c | 1 + Source/C/RequiredEventHandlers.c | 1 + Source/C/SCRN.c | 1 + Source/C/SaveOpen.c | 1 + Source/C/SendAppleEvents.c | 1 + Source/C/SlideControlsWindow.c | 1 + Source/C/SlideShow.c | 1 + Source/C/SlideShowOptions.c | 1 + Source/C/StandardFolder.c | 1 + Source/C/StatisticsWindow.c | 1 + Source/C/TIFF.c | 1 + Source/C/TIFFTables.c | 1 + Source/C/UpdateRegion.c | 1 + Source/C/ViewMenu.c | 1 + Source/C/WindowMenu.c | 1 + Source/C/WindowUtils.c | 1 + Source/C/cApplication.c | 1 + Source/C/cDocument.c | 1 + Source/C/cDrawingArea.c | 1 + Source/C/cFile.c | 1 + Source/C/cImage.c | 1 + Source/C/cPixelMap.c | 1 + Source/C/cSelection.c | 1 + Source/C/cWindow.c | 1 + 327 files changed, 298 insertions(+) create mode 100644 Headers/AppleEventUtils.h create mode 100644 Headers/AppleMenu.h create mode 100644 Headers/BMP.h create mode 100644 Headers/Bottlenecks.h create mode 100644 Headers/ColorsMenu.h create mode 100644 Headers/ColorsWindow.h create mode 100644 Headers/CommentsWindow.h create mode 100644 Headers/CompressedResource.h create mode 100644 Headers/CoreEventHandlers.h create mode 100644 Headers/CustomCopyBits.h create mode 100644 Headers/DialogUtils.h create mode 100644 Headers/EditMenu.h create mode 100644 Headers/EventHandlers.h create mode 100644 Headers/EventUtils.h create mode 100644 Headers/FileMenu.h create mode 100644 Headers/FloatingWindows.h create mode 100644 Headers/GIF.h create mode 100644 Headers/GeneralMenus.h create mode 100644 Headers/HelpMenu.h create mode 100644 Headers/ImageUtils.h create mode 100644 Headers/JPEG.h create mode 100644 Headers/JPEGNoQuickTime.h create mode 100644 Headers/JPEGView.h create mode 100644 Headers/JPEGView.h.o create mode 100644 Headers/JPEGView.r.h create mode 100644 Headers/JPEGViewEventHandlers.h create mode 100644 Headers/JPEGViewGlobals.h create mode 100644 Headers/JPEGViewPlugIn.h create mode 100644 Headers/JPEGViewTypes.h create mode 100644 Headers/MW.Header.68k create mode 100644 Headers/MW.Header.PPC create mode 100644 Headers/MarchingAnts.h create mode 100644 Headers/MemoryUtils.h create mode 100644 Headers/MercutioAPI.h create mode 100644 Headers/MiscellaneousUtils.h create mode 100644 Headers/MonitorUtils.h create mode 100644 Headers/PICT.h create mode 100644 Headers/PNTG.h create mode 100644 Headers/Preferences.h create mode 100644 Headers/ProgressProcs.h create mode 100644 Headers/QDxDispatchPatch.h create mode 100644 Headers/Quantize.h create mode 100644 Headers/QuickDrawUtils.h create mode 100644 Headers/RequiredEventHandlers.h create mode 100644 Headers/SCRN.h create mode 100644 Headers/SaveOpen.h create mode 100644 Headers/SendAppleEvents.h create mode 100644 Headers/SlideControlsWindow.h create mode 100644 Headers/SlideShow.h create mode 100644 Headers/SlideShowOptions.h create mode 100644 Headers/StandardFolder.h create mode 100644 Headers/StatisticsWindow.h create mode 100644 Headers/TIFF.h create mode 100644 Headers/ViewMenu.h create mode 100644 Headers/WindowMenu.h create mode 100644 Headers/WindowUtils.h create mode 100644 Headers/cApplication.h create mode 100644 Headers/cDocument.h create mode 100644 Headers/cDrawingArea.h create mode 100644 Headers/cFile.h create mode 100644 Headers/cImage.h create mode 100644 Headers/cPixelMap.h create mode 100644 Headers/cSelection.h create mode 100644 Headers/cWindow.h create mode 100644 Headers/jconfig.h create mode 100644 Headers/jerror.h create mode 100644 Headers/jmorecfg.h create mode 100644 Headers/jpeglib.h create mode 100644 Headers/jversion.h create mode 100644 Independent JPEG Group/Changed/jconfig.h create mode 100644 Independent JPEG Group/Changed/jdcolor.c create mode 100644 Independent JPEG Group/Changed/jmorecfg.h create mode 100644 Independent JPEG Group/JPEGLib.o create mode 100644 Independent JPEG Group/JPEGLib.xcoff create mode 100644 Independent JPEG Group/JPEGLib.µ create mode 100644 Independent JPEG Group/Makefile.TXT create mode 100644 Independent JPEG Group/README.TXT create mode 100644 Independent JPEG Group/ansi2knr.1 create mode 100644 Independent JPEG Group/ansi2knr.c create mode 100644 Independent JPEG Group/cderror.h create mode 100644 Independent JPEG Group/cdjpeg.h create mode 100644 Independent JPEG Group/change.log create mode 100644 Independent JPEG Group/cjpeg.1 create mode 100644 Independent JPEG Group/cjpeg.c create mode 100644 Independent JPEG Group/ckconfig.c create mode 100644 Independent JPEG Group/coderules.doc create mode 100644 Independent JPEG Group/configure_.TXT create mode 100644 Independent JPEG Group/djpeg.1 create mode 100644 Independent JPEG Group/djpeg.c create mode 100644 Independent JPEG Group/example.c create mode 100644 Independent JPEG Group/filelist.doc create mode 100644 Independent JPEG Group/install.doc create mode 100644 Independent JPEG Group/jcapi.c create mode 100644 Independent JPEG Group/jccoefct.c create mode 100644 Independent JPEG Group/jccolor.c create mode 100644 Independent JPEG Group/jcdctmgr.c create mode 100644 Independent JPEG Group/jchuff.c create mode 100644 Independent JPEG Group/jcmainct.c create mode 100644 Independent JPEG Group/jcmarker.c create mode 100644 Independent JPEG Group/jcmaster.c create mode 100644 Independent JPEG Group/jcomapi.c create mode 100644 Independent JPEG Group/jconfig.auto create mode 100644 Independent JPEG Group/jconfig.bcc create mode 100644 Independent JPEG Group/jconfig.doc create mode 100644 Independent JPEG Group/jconfig.h create mode 100644 Independent JPEG Group/jconfig.manx create mode 100644 Independent JPEG Group/jconfig.mc6 create mode 100644 Independent JPEG Group/jconfig.sas create mode 100644 Independent JPEG Group/jconfig.st create mode 100644 Independent JPEG Group/jconfig.vms create mode 100644 Independent JPEG Group/jcparam.c create mode 100644 Independent JPEG Group/jcprepct.c create mode 100644 Independent JPEG Group/jcsample.c create mode 100644 Independent JPEG Group/jdapi.c create mode 100644 Independent JPEG Group/jdatadst.c create mode 100644 Independent JPEG Group/jdatasrc.c create mode 100644 Independent JPEG Group/jdcoefct.c create mode 100644 Independent JPEG Group/jdcolor.c create mode 100644 Independent JPEG Group/jdct.h create mode 100644 Independent JPEG Group/jddctmgr.c create mode 100644 Independent JPEG Group/jdhuff.c create mode 100644 Independent JPEG Group/jdmainct.c create mode 100644 Independent JPEG Group/jdmarker.c create mode 100644 Independent JPEG Group/jdmaster.c create mode 100644 Independent JPEG Group/jdpostct.c create mode 100644 Independent JPEG Group/jdsample.c create mode 100644 Independent JPEG Group/jerror.c create mode 100644 Independent JPEG Group/jerror.h create mode 100644 Independent JPEG Group/jfdctllm.c create mode 100644 Independent JPEG Group/jidctllm.c create mode 100644 Independent JPEG Group/jidctred.c create mode 100644 Independent JPEG Group/jinclude.h create mode 100644 Independent JPEG Group/jmemansi.c create mode 100644 Independent JPEG Group/jmemdos.c create mode 100644 Independent JPEG Group/jmemdosa.asm create mode 100644 Independent JPEG Group/jmemmgr.c create mode 100644 Independent JPEG Group/jmemname.c create mode 100644 Independent JPEG Group/jmemnobs.c create mode 100644 Independent JPEG Group/jmemsys.h create mode 100644 Independent JPEG Group/jmorecfg.h create mode 100644 Independent JPEG Group/jpegint.h create mode 100644 Independent JPEG Group/jpeglib.h create mode 100644 Independent JPEG Group/jquant1.c create mode 100644 Independent JPEG Group/jquant2.c create mode 100644 Independent JPEG Group/jutils.c create mode 100644 Independent JPEG Group/jversion.h create mode 100644 Independent JPEG Group/libjpeg.doc create mode 100644 Independent JPEG Group/makcjpeg.st create mode 100644 Independent JPEG Group/makdjpeg.st create mode 100644 Independent JPEG Group/makefile.ansi create mode 100644 Independent JPEG Group/makefile.auto create mode 100644 Independent JPEG Group/makefile.bcc create mode 100644 Independent JPEG Group/makefile.manx create mode 100644 Independent JPEG Group/makefile.mc6 create mode 100644 Independent JPEG Group/makefile.mms create mode 100644 Independent JPEG Group/makefile.sas create mode 100644 Independent JPEG Group/makefile.unix create mode 100644 Independent JPEG Group/makefile.vms create mode 100644 Independent JPEG Group/makljpeg.st create mode 100644 Independent JPEG Group/makvms.opt create mode 100644 Independent JPEG Group/rdgif.c create mode 100644 Independent JPEG Group/rdppm.c create mode 100644 Independent JPEG Group/rdtarga.c create mode 100644 Independent JPEG Group/structure.doc create mode 100644 Independent JPEG Group/testimg.jpg create mode 100644 Independent JPEG Group/testorig.jpg create mode 100644 Independent JPEG Group/usage.doc create mode 100644 Independent JPEG Group/wrgif.c create mode 100644 Independent JPEG Group/wrppm.c create mode 100644 Infinity Windoid 2_6/Infinity Windoid.makeout create mode 100644 Infinity Windoid 2_6/InfinityWDEF.pef create mode 100644 Infinity Windoid 2_6/InfinityWDEF.r create mode 100644 Infinity Windoid 2_6/Makefile.TXT create mode 100644 Infinity Windoid 2_6/WindoidDefines.h create mode 100644 Infinity Windoid 2_6/obj/InfinityWDEF.xcoff create mode 100644 JFIF Preview/JFIFPreview.c create mode 100644 JFIF Preview/JFIFPreview.fat.r create mode 100644 JFIF Preview/JFIFPreview.r create mode 100644 JFIF Preview/Makefile.TXT create mode 100644 JFIF Preview/obj/InfinityWDEF.xcoff create mode 100644 JFIF Preview/obj/JFIFPreview.c.o create mode 100644 JFIF Preview/obj/JFIFPreview.o create mode 100644 JPEGView 3 3 docs.pdf create mode 100644 JPEGView 3_3 ƒ/JPEGView create mode 100644 JPEGView 3_3 ƒ/JPEGView 3.3 Blurb create mode 100644 JPEGView 3_3 ƒ/Parrots JPEG.JPG create mode 100644 JPEGView 3_3 ƒ/Possible Conflicts create mode 100644 JPEGView 3_3 ƒ/Read Me 3.3! create mode 100644 JPEGView Read Me create mode 100644 Libraries/JPEGLib.o create mode 100644 Libraries/JPEGLib.xcoff create mode 100644 Make Resources.TXT create mode 100644 Makefile.TXT create mode 100644 New in JPEGView 3.3 create mode 100644 Pictures/Atlas Rocket.PCT create mode 100644 Pictures/Earth Color.PCT create mode 100644 Pictures/Eclipse.PCT create mode 100644 Pictures/Escher-Snakes.PCT create mode 100644 Pictures/Hubble Deployment.PCT create mode 100644 Pictures/JPEGView About.PCT create mode 100644 Pictures/PacMan.PCT create mode 100644 Pictures/Sarah Bernhardt.PCT create mode 100644 Pictures/Star Wars-Death Star.PCT create mode 100644 Pictures/Yellow_Purple.PCT create mode 100644 Read Me!.TXT create mode 100644 Resources/DialogHelpResources.r create mode 100644 Resources/DialogResources.r create mode 100644 Resources/GeneralHelpResources.r create mode 100644 Resources/GeneralResources.r create mode 100644 Resources/Help Text/01.Overview create mode 100644 Resources/Help Text/02.Viewing Images create mode 100644 Resources/Help Text/03.Floating Windows create mode 100644 Resources/Help Text/04.Special Effects create mode 100644 Resources/Help Text/05.Colors & Reduction create mode 100644 Resources/Help Text/06.Saving Images create mode 100644 Resources/Help Text/07.Slide Show create mode 100644 Resources/Help Text/08.Preferences Settings create mode 100644 Resources/Help Text/09.File Formats create mode 100644 Resources/Help Text/10.Scripting JPEGView create mode 100644 Resources/Help Text/11.General JPEG Q&A create mode 100644 Resources/Help Text/12.JPEGView Q&A create mode 100644 Resources/Help Text/13.Hints And Tips create mode 100644 Resources/Help Text/14.Contacting the Author create mode 100644 Resources/Help Text/15.Acknowledgements create mode 100644 Resources/Help Text/16.Program History create mode 100644 Resources/Help Text/Technical Information.TXT create mode 100644 Resources/MenuHelpResources.r create mode 100644 Resources/MenuResources.r create mode 100644 Resources/PowerPCResources.r create mode 100644 Resources/aeteResource.r create mode 100644 Source/68020/CopyFastScaledFrom32.a create mode 100644 Source/68020/CopyReallyFastScaledFrom32.a create mode 100644 Source/68020/CopyScaledFrom32.a create mode 100644 Source/68020/CopyTo32.a create mode 100644 Source/68020/CopyUnscaledFrom32.a create mode 100644 Source/68020/CustomCopyBits.a create mode 100644 Source/68020/DecodeDummyRow.a create mode 100644 Source/68020/DecodeRow.a create mode 100644 Source/68020/DitherCopyTo16Even.a create mode 100644 Source/68020/DitherCopyTo16Odd.a create mode 100644 Source/68020/DitherCopyTo8Even.a create mode 100644 Source/68020/DitherCopyTo8Odd.a create mode 100644 Source/68020/FillHistogram16.a create mode 100644 Source/68020/FillHistogram32.a create mode 100644 Source/68020/GIF.a create mode 100644 Source/68020/InitRegion.a create mode 100644 Source/68020/QDxDispatchPatch.a create mode 100644 Source/68020/Quantize.a create mode 100644 Source/68020/UpdateRegion.a create mode 100644 Source/C/AppleEventUtils.c create mode 100644 Source/C/AppleMenu.c create mode 100644 Source/C/BMP.c create mode 100644 Source/C/Bottlenecks.c create mode 100644 Source/C/ColorsMenu.c create mode 100644 Source/C/ColorsWindow.c create mode 100644 Source/C/CommentsWindow.c create mode 100644 Source/C/CompressedResource.c create mode 100644 Source/C/CopyFastScaledFrom32.c create mode 100644 Source/C/CopyFastScaledFrom32.c copy create mode 100644 Source/C/CopyReallyFastScaledFrom32.c create mode 100644 Source/C/CopyScaledFrom32.c create mode 100644 Source/C/CopyScaledFrom32.c.float create mode 100644 Source/C/CopyTo32.c create mode 100644 Source/C/CopyUnscaledFrom32.c create mode 100644 Source/C/CoreEventHandlers.c create mode 100644 Source/C/CustomCopyBits.c create mode 100644 Source/C/DecodeDummyRow.c create mode 100644 Source/C/DecodeRow.c create mode 100644 Source/C/DialogUtils.c create mode 100644 Source/C/DitherCopyTo16Even.c create mode 100644 Source/C/DitherCopyTo16Odd.c create mode 100644 Source/C/DitherCopyTo8Even.c create mode 100644 Source/C/DitherCopyTo8Odd.c create mode 100644 Source/C/EditMenu.c create mode 100644 Source/C/EventHandlers.c create mode 100644 Source/C/EventUtils.c create mode 100644 Source/C/FileMenu.c create mode 100644 Source/C/FillHistogram16.c create mode 100644 Source/C/FillHistogram32.c create mode 100644 Source/C/FloatingWindows.c create mode 100644 Source/C/GIF.c create mode 100644 Source/C/GeneralMenus.c create mode 100644 Source/C/HelpMenu.c create mode 100644 Source/C/IJGJPEG.c create mode 100644 Source/C/ImageUtils.c create mode 100644 Source/C/InitRegion.c create mode 100644 Source/C/JPEG.c create mode 100644 Source/C/JPEGNoQuickTime.c create mode 100644 Source/C/JPEGView.c create mode 100644 Source/C/JPEGViewEventHandlers.c create mode 100644 Source/C/JPEGViewGlobals.c create mode 100644 Source/C/MarchingAnts.c create mode 100644 Source/C/MemoryUtils.c create mode 100644 Source/C/MercutioAPI.c create mode 100644 Source/C/MiscellaneousUtils.c create mode 100644 Source/C/MonitorUtils.c create mode 100644 Source/C/PICT.c create mode 100644 Source/C/PNTG.c create mode 100644 Source/C/PowerPCStub.c create mode 100644 Source/C/Preferences.c create mode 100644 Source/C/ProgressProcs.c create mode 100644 Source/C/QDxDispatchPatch.c create mode 100644 Source/C/Quantize.c create mode 100644 Source/C/QuickDrawUtils.c create mode 100644 Source/C/RequiredEventHandlers.c create mode 100644 Source/C/SCRN.c create mode 100644 Source/C/SaveOpen.c create mode 100644 Source/C/SendAppleEvents.c create mode 100644 Source/C/SlideControlsWindow.c create mode 100644 Source/C/SlideShow.c create mode 100644 Source/C/SlideShowOptions.c create mode 100644 Source/C/StandardFolder.c create mode 100644 Source/C/StatisticsWindow.c create mode 100644 Source/C/TIFF.c create mode 100644 Source/C/TIFFTables.c create mode 100644 Source/C/UpdateRegion.c create mode 100644 Source/C/ViewMenu.c create mode 100644 Source/C/WindowMenu.c create mode 100644 Source/C/WindowUtils.c create mode 100644 Source/C/cApplication.c create mode 100644 Source/C/cDocument.c create mode 100644 Source/C/cDrawingArea.c create mode 100644 Source/C/cFile.c create mode 100644 Source/C/cImage.c create mode 100644 Source/C/cPixelMap.c create mode 100644 Source/C/cSelection.c create mode 100644 Source/C/cWindow.c diff --git a/Headers/AppleEventUtils.h b/Headers/AppleEventUtils.h new file mode 100644 index 0000000..54969b8 --- /dev/null +++ b/Headers/AppleEventUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __APPLEEVENTUTILS__ #define __APPLEEVENTUTILS__ /* * sObjectToken = generic token for all our AE object accessors */ typedef struct ObjectToken { short count; DescType objclass, property; Ptr object[1]; } ObjectToken, *ObjectTokenPtr, **ObjectTokenHandle; void AppleEventInit(void); pascal OSErr HandleUnsupportedEvent(AppleEvent *theEvent, AppleEvent *reply, long refCon); OSErr AENewEvent(AppleEvent *theEvent, AEEventClass theClass, AEEventID theID); OSErr AEMakeIntlDesc(StringPtr theString, AEDesc *theDesc); OSErr AEMakeBeginningILoc(AEDesc *theDesc, Boolean floating); OSErr AECreateHandleDesc(DescType theType, Handle theHandle, AEDesc *theDesc); OSErr AEAddAlias(AppleEvent *theEvent, AEKeyword theKey, FSSpec *theSpec); OSErr AEAddAliasList(AppleEvent *theEvent, AEKeyword theKey, FSSpec *theSpec, short count); OSErr AEExtractObject(AppleEvent *theEvent, AEKeyword theKey, AEDesc *theToken); OSErr AEExtractInsertionLoc(AppleEvent *theEvent, AEKeyword theKey, WindowPtr *theWindow); OSErr AEExtractGeneric(AppleEvent *theEvent, AEKeyword theKey, DescType theType, Size theSize, void *theData); OSErr AEExtractTypeList(AppleEvent *theEvent, AEKeyword theKey, DescType ***theData); OSErr AEExtractPString(AppleEvent *theEvent, AEKeyword theKey, uchar *theString); pascal OSErr AECoerceIntlToChar(DescType fromType, Ptr theData, Size theSize, DescType toType, long refCon, AEDesc *result); pascal OSErr AECoerceRectToList(DescType fromType, Ptr theData, Size theSize, DescType toType, long refCon, AEDesc *result); pascal OSErr AECoerceListToRect(AEDesc *theAEDesc, DescType toType, long refCon, AEDesc *result); pascal OSErr AECoerceRealToFixed(DescType fromType, Ptr theData, Size theSize, DescType toType, long refCon, AEDesc *result); pascal OSErr AECoerceFixedToReal(DescType fromType, Ptr theData, Size theSize, DescType toType, long refCon, AEDesc *result); pascal Boolean AEIdleProc(EventRecord *theEvent, long *sleep, RgnHandle *mouseRgn); #define AEBegin() gInAppleEvent = true #define AEEnd() gInAppleEvent = false #define AEAddBoolean(evt, key, data) AEPutParamPtr(evt, key, typeBoolean, (void *)data, sizeof(Boolean)) #define AEAddShort(evt, key, data) AEPutParamPtr(evt, key, typeShortInteger, (void *)data, sizeof(short)) #define AEAddLong(evt, key, data) AEPutParamPtr(evt, key, typeLongInteger, (void *)data, sizeof(long)) #define AEAddFixed(evt, key, data) AEPutParamPtr(evt, key, typeFixed, (void *)data, sizeof(long)) #define AEAddType(evt, key, data) AEPutParamPtr(evt, key, typeType, (void *)data, sizeof(DescType)) #define AEAddEnumerated(evt, key, data) AEPutParamPtr(evt, key, typeEnumerated, (void *)data, sizeof(DescType)) #define AEAddQDRectangle(evt, key, data) AEPutParamPtr(evt, key, typeQDRectangle, (void *)data, sizeof(Rect)) #define AEExtractAlias(event, key, ptr) AEExtractGeneric(event, key, typeFSS, sizeof(FSSpec), ptr) #define AEExtractBoolean(event, key, ptr) AEExtractGeneric(event, key, typeBoolean, sizeof(Boolean), ptr) #define AEExtractShort(event, key, ptr) AEExtractGeneric(event, key, typeShortInteger, sizeof(short), ptr) #define AEExtractLong(event, key, ptr) AEExtractGeneric(event, key, typeLongInteger, sizeof(long), ptr) #define AEExtractFixed(event, key, ptr) AEExtractGeneric(event, key, typeFixed, sizeof(Fixed), ptr) #define AEExtractType(event, key, ptr) AEExtractGeneric(event, key, typeType, sizeof(DescType), ptr) #define AEExtractEnumerated(event, key, ptr) AEExtractGeneric(event, key, typeEnumerated, sizeof(DescType), ptr) #define AEExtractQDRectangle(event, key, ptr) AEExtractGeneric(event, key, typeQDRectangle, sizeof(Rect), ptr) #endif \ No newline at end of file diff --git a/Headers/AppleMenu.h b/Headers/AppleMenu.h new file mode 100644 index 0000000..66d208b --- /dev/null +++ b/Headers/AppleMenu.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __APPLEMENU__ #define __APPLEMENU__ void HandleAppleChoice(short theItem); void OpenAbout(void); void OpenAboutHelp(void); void HandleAboutHelpEvent(short theItem); WindowPtr GetAboutHelpWindow(void); #endif \ No newline at end of file diff --git a/Headers/BMP.h b/Headers/BMP.h new file mode 100644 index 0000000..62bb3a4 --- /dev/null +++ b/Headers/BMP.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __BMP__ #define __BMP__ extern Boolean idBMP(uchar *theData, long theSize, short refNum, FSSpec *theSpec); extern OSErr OpenBMP(ImageHandle theImage); extern OSErr DrawBMP(Handle theHandle, JVDrawParamsHandle theParams); extern OSErr CloneBMP(ImageHandle origImage, ImageHandle newImage); extern OSErr CloseBMP(ImageHandle theImage); #endif \ No newline at end of file diff --git a/Headers/Bottlenecks.h b/Headers/Bottlenecks.h new file mode 100644 index 0000000..46f0f6b --- /dev/null +++ b/Headers/Bottlenecks.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __JV_DRAWING_H__ #define __JV_DRAWING_H__ extern OSErr DrawingInit(void); extern JVDrawParamsHandle NewDrawParams(Rect *bounds, short quality, Boolean quantize, NestedProgressPtr progress, Handle privateData); extern void SetUpDrawPort(JVDrawParamsHandle theParams, short whichPort, CGrafPtr thePort, Rect *srcRect, Rect *dstRect, Boolean dither); extern OSErr PreflightDrawing(JVDrawParamsHandle theParams); extern OSErr PostflightDrawing(JVDrawParamsHandle theParams); extern OSErr FixBits(CGrafPtr thePort, Boolean on); extern void CallProperBitsProc(BitMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask); extern void CallProperTextProc(short count, Ptr textAddr, Point numer, Point denom); extern void CallProperLineProc(Point newPt); extern void CallProperRectProc(GrafVerb verb, Rect *r); extern void CallProperRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight); extern void CallProperOvalProc(GrafVerb verb, Rect *r); extern void CallProperArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle); extern void CallProperPolyProc(GrafVerb verb, PolyHandle poly); extern void CallProperRgnProc(GrafVerb verb, RgnHandle rgn); extern void CallProperPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags); enum { kOnscreenPort = 0, kOffscreenPort1, kOffscreenPort2 }; #endif \ No newline at end of file diff --git a/Headers/ColorsMenu.h b/Headers/ColorsMenu.h new file mode 100644 index 0000000..82d9c2a --- /dev/null +++ b/Headers/ColorsMenu.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __COLORSMENU__ #define __COLORSMENU__ void HandleColorChoice(short theItem); void HandleQualityChoice(short theItem); #define SystemPalette(depth) ((depth < 8) ? gColorPalette[depth] : gColorPalette[8]) #define GreyPalette(depth) ((depth < 8) ? gGreyPalette[depth] : gGreyPalette[8]) #endif \ No newline at end of file diff --git a/Headers/ColorsWindow.h b/Headers/ColorsWindow.h new file mode 100644 index 0000000..c433122 --- /dev/null +++ b/Headers/ColorsWindow.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __COLORSWINDOW__ #define __COLORSWINDOW__ OSErr OpenColors(void); void CloseColors(void); WindowPtr GetColorsWindow(void); void DrawColorsWindow(void); void DoColorsHelp(Point mouseLoc); #endif \ No newline at end of file diff --git a/Headers/CommentsWindow.h b/Headers/CommentsWindow.h new file mode 100644 index 0000000..a6db201 --- /dev/null +++ b/Headers/CommentsWindow.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __COMMENTSWINDOW__ #define __COMMENTSWINDOW__ OSErr OpenComments(void); void CloseComments(void); void NudgeComments(Rect *oldRect); WindowPtr GetCommentsWindow(void); void DrawCommentsWindow(void); void UpdateCommentsWindow(void); void DoCommentsHelp(Point mouseLoc); extern void HandleCommentsClick(EventRecord *theEvent); #endif \ No newline at end of file diff --git a/Headers/CompressedResource.h b/Headers/CompressedResource.h new file mode 100644 index 0000000..0507011 --- /dev/null +++ b/Headers/CompressedResource.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __COMPRESSEDRESOURCE__ #define __COMPRESSEDRESOURCE__ Handle GetCompResource(OSType theType, short theID); #endif \ No newline at end of file diff --git a/Headers/CoreEventHandlers.h b/Headers/CoreEventHandlers.h new file mode 100644 index 0000000..79433b4 --- /dev/null +++ b/Headers/CoreEventHandlers.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __COREEVENTHANDLERS__ #define __COREEVENTHANDLERS__ pascal OSErr HandleClone(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleClose(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleCountElements(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleCreateElement(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleDelete(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleDoObjectsExist(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleGetData(AppleEvent *theEvent, AppleEvent *reply, long refCon); OSErr DoGetData(DescType theType, ObjectTokenHandle theToken, short index, DescType typeWanted, AEDesc *theData); pascal OSErr HandleGetDataSize(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleMove(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleSave(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandleSetData(AppleEvent *theEvent, AppleEvent *reply, long refCon); OSErr DoSetData(DescType theType, ObjectTokenHandle theToken, short index, AEDesc *theData); #endif \ No newline at end of file diff --git a/Headers/CustomCopyBits.h b/Headers/CustomCopyBits.h new file mode 100644 index 0000000..0f5a13f --- /dev/null +++ b/Headers/CustomCopyBits.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CUSTOMCOPYBITS__ #define __CUSTOMCOPYBITS__ extern void DoCustomCopy(PixMap *src, PixMap *dst, Rect *srcRect, Rect *dstRect, Boolean fast, short depth); #endif \ No newline at end of file diff --git a/Headers/DialogUtils.h b/Headers/DialogUtils.h new file mode 100644 index 0000000..7ad5498 --- /dev/null +++ b/Headers/DialogUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __DIALOGUTILS__ #define __DIALOGUTILS__ enum { kIndefProgress = 0x7d8d9dadL, kModalProgress = 0x7d8d9daeL }; extern short HandleDialogLetterKey(DialogPtr theDialog, char theChar); extern short HandleDialogCancelKey(DialogPtr theDialog); extern short HandleDialogOKKey(DialogPtr theDialog); extern Boolean IsDialogWindow(WindowPtr theWindow); extern void UpdateParamText(StringPtr string1, StringPtr string2, StringPtr string3, StringPtr string4); extern pascal void PopUpMenuBox(DialogPtr theDialog, short theItem); Point CenterWindow(WindowPtr theWindow); void GetMouseGDRect(Rect *theRect); void MouseCenterRect(Rect *theRect); short CenterAlert(short id); short CenterDialog(short id); Point CenterDialogWhere(short id); pascal Boolean GenericFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit); pascal void OutlineOK(DialogPtr theDialog, short theItem); pascal void LineItem(DialogPtr theDialog, short theItem); void SetItemHandle(DialogPtr theDialog, short theItem, Handle newHandle); void DisableDControl(DialogPtr theDialog, short theItem); void EnableDControl(DialogPtr theDialog, short theItem); void SetDCtlValue(DialogPtr theDialog, short theItem, short theValue); short GetDCtlValue(DialogPtr theDialog, short theItem); void SetDIText(DialogPtr theDialog, short theItem, Str255 theText); void GetDIText(DialogPtr theDialog, short theItem, Str255 theText); void UpdateDialogItem(DialogPtr theDialog, short theItem); #endif \ No newline at end of file diff --git a/Headers/EditMenu.h b/Headers/EditMenu.h new file mode 100644 index 0000000..7cd253d --- /dev/null +++ b/Headers/EditMenu.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __EDITMENU__ #define __EDITMENU__ void HandleEditChoice(short theItem); void DoSelectScreen(ImageHandle theImage); extern void SelRectToCropRect(ImageHandle theImage, Rect *newRect); #endif \ No newline at end of file diff --git a/Headers/EventHandlers.h b/Headers/EventHandlers.h new file mode 100644 index 0000000..e6c6c32 --- /dev/null +++ b/Headers/EventHandlers.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __EVENTHANDLERS__ #define __EVENTHANDLERS__ extern void MainEventLoop(void); extern void DispatchMainEvent(EventRecord *theEvent, Boolean isDialogEvent); extern void HandleNullEvent(void); extern void DispatchBalloonHelp(void); extern void EnsureFrontmost(void); extern void HandleMouseDownDialog(EventRecord *theEvent); extern void HandleMouseDownEvent(EventRecord *theEvent); extern void HandleMenuClick(EventRecord *theEvent); extern void HandleContentClick(EventRecord *theEvent, WindowPtr theWindow); extern void HandleDragClick(EventRecord *theEvent, WindowPtr theWindow); extern void HandleCloseClick(EventRecord *theEvent, WindowPtr theWindow); extern void HandleGrowClick(EventRecord *theEvent, WindowPtr theWindow); extern void HandleZoomClick(EventRecord *theEvent, short thePart, WindowPtr theWindow); extern void HandleKeyDownDialog(EventRecord *theEvent); extern void HandleKeyDownEvent(EventRecord *theEvent); extern void HandleActivateDialog(EventRecord *theEvent); extern void HandleActivateEvent(EventRecord *theEvent); extern void HandleUpdateDialog(EventRecord *theEvent); extern void HandleUpdateEvent(EventRecord *theEvent); extern void HandleOSEvent(EventRecord *theEvent); extern void HandleDiskEvent(EventRecord *theEvent); extern void DispatchDialogEvent(DialogPtr theDialog, short theItem); extern void MyInvalMenuBar(void); #endif \ No newline at end of file diff --git a/Headers/EventUtils.h b/Headers/EventUtils.h new file mode 100644 index 0000000..7b7c3b9 --- /dev/null +++ b/Headers/EventUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __EVENTUTILS__ #define __EVENTUTILS__ extern void UpdateCursor(RgnHandle theRgn); extern Boolean TrackSelRect(Point theAnchor, ImageHandle theImage); extern Boolean TrackDragRect(Point theAnchor, ImageHandle theImage); extern Boolean TrackGrowWindow(Point thePoint, ImageHandle theImage, Boolean constrain, Rect *newRect); #endif \ No newline at end of file diff --git a/Headers/FileMenu.h b/Headers/FileMenu.h new file mode 100644 index 0000000..89f09a6 --- /dev/null +++ b/Headers/FileMenu.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __FILEMENU__ #define __FILEMENU__ void HandleFileChoice(short theItem); void DoOpenDialog(void); pascal Boolean OpenSaveModalFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit, void *yourDataPtr); pascal Boolean OpenFileFilter(CInfoPBPtr pb, Boolean *dummy); pascal short OpenDialogHook(short item, DialogPtr theDialog, long dummy); void ScanDirFiles(void); void DoSaveDialog(void); void UpdateSaveButtons(DialogPtr theDialog); pascal short SaveDialogHook(short item, DialogPtr theDialog, long dummy); extern Boolean ValidType(OSType theType); #endif \ No newline at end of file diff --git a/Headers/FloatingWindows.h b/Headers/FloatingWindows.h new file mode 100644 index 0000000..a799d56 --- /dev/null +++ b/Headers/FloatingWindows.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __FLOATINGWINDOWS__ #define __FLOATINGWINDOWS__ #include #include // Activate/deactivate floating windows & frontmost window extern void FWActivate(void); extern void FWDeactivate(void); // Show/hide all the floating windows extern void FWHideFloatingWindows(void); extern void FWShowFloatingWindows(void); // Create new floating windows extern WindowPtr FWGetNewFloatingWindow(short resID, Ptr wStorage, WindowPtr behind); extern WindowPtr FWNewFloatingWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon); // Determine if a window is floating extern Boolean FWIsFloating(WindowPtr theWindow); // Window locating routines extern WindowPtr FWBottomDialog(void); extern WindowPtr FWBottomFloatingWindow(void); extern WindowPtr FWBottomWindow(void); extern WindowPtr FWTopDialog(void); extern WindowPtr FWTopFloatingWindow(void); extern WindowPtr FWTopWindow(void); // Alert function substitutes extern short FWAlert(short alertID, ModalFilterUPP filterProc); extern short FWCautionAlert(short alertID, ModalFilterUPP filterProc); extern short FWNoteAlert(short alertID, ModalFilterUPP filterProc); extern short FWStopAlert(short alertID, ModalFilterUPP filterProc); // Dialog Manager substitutes extern void FWCloseDialog(DialogPtr theDialog); extern void FWDisposeDialog(DialogPtr theDialog); extern Boolean FWDialogSelect(EventRecord *theEvent, DialogPtr *whichDlog, short *itemHit); extern Boolean FWIsDialogEvent(EventRecord *theEvent); extern DialogPtr FWGetNewDialog(short dlgRsrcID, Ptr dStorage, WindowPtr behind); extern DialogPtr FWNewCDialog(Ptr dStorage, Rect *wRect, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon, Handle itemList); extern DialogPtr FWNewDialog(Ptr dStorage, Rect *wRect, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon, Handle itemList); // Window manager substitutes extern void FWCloseWindow(WindowPtr theWindow); extern void FWDisposeWindow(WindowPtr theWindow); extern void FWDragWindow(WindowPtr theWindow, Point startPoint, Rect *limitRect); extern WindowPtr FWFrontWindow(void); extern WindowPtr FWGetNewCWindow(short resID, Ptr wStorage, WindowPtr behind); extern WindowPtr FWGetNewWindow(short resID, Ptr wStorage, WindowPtr behind); extern void FWHideWindow(WindowPtr theWindow); extern void FWMoveWindow(WindowPtr theWindow, short hGlobal, short vGlobal, Boolean front); extern WindowPtr FWNewCWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon); extern WindowPtr FWNewWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon); extern void FWSelectWindow(WindowPtr theWindow); extern void FWShowWindow(WindowPtr theWindow); // Window manager interfaces extern WindowPtr GetFirstWindow(void); extern WindowPtr NextWindow(WindowPtr theWindow); extern short WindowKind(WindowPtr theWindow); extern Boolean WindowVisible(WindowPtr theWindow); extern Boolean WindowHilited(WindowPtr theWindow); extern RgnHandle GetStrucRgn(WindowPtr theWindow); extern RgnHandle GetContRgn(WindowPtr theWindow); extern Boolean HasGoAway(WindowPtr theWindow); extern void SetWindowKind(WindowPtr theWindow, short theKind); extern void SetNextWindow(WindowPtr theWindow, WindowPtr nextWindow); extern void SetFirstWindow(WindowPtr theWindow); // Floating window constants enum { floatingWindowKind = 'fl' }; #endif \ No newline at end of file diff --git a/Headers/GIF.h b/Headers/GIF.h new file mode 100644 index 0000000..7e6d158 --- /dev/null +++ b/Headers/GIF.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __GIF__ #define __GIF__ extern Boolean idGIF(uchar *theData, long theSize, short refNum, FSSpec *theSpec); extern OSErr OpenGIF(ImageHandle theImage); extern OSErr DrawGIF(Handle theHandle, JVDrawParamsHandle theParams); #endif \ No newline at end of file diff --git a/Headers/GeneralMenus.h b/Headers/GeneralMenus.h new file mode 100644 index 0000000..b59686c --- /dev/null +++ b/Headers/GeneralMenus.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __GENERALMENUS__ #define __GENERALMENUS__ void MenuBarInit(void); extern long MakeMenuSelection(short menu, short item); extern void HandleMenuChoice(long theChoice); void SaveMenuArea(void); void RestoreMenuArea(void); void DisableMenus(void); void EnableMenus(void); void AdjustMenus(void); void AdjustFile(short var); void AdjustEdit(short var); Boolean CanSelectScreen(void); void AdjustView(short var); void AdjustColor(short var); void AdjustWindow(short var); void AddWindowItem(ImageHandle theImage); void DeleteWindowItem(ImageHandle theImage); #define MenuEnable(menu, item, enabled) \ if (enabled) EnableItem(menu, item);\ else DisableItem(menu, item) #define SetMBarHeight(ht) (*(short *)MBarHeight = (ht)) #endif \ No newline at end of file diff --git a/Headers/HelpMenu.h b/Headers/HelpMenu.h new file mode 100644 index 0000000..63d2ed6 --- /dev/null +++ b/Headers/HelpMenu.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __HELPMENU__ #define __HELPMENU__ extern void HandleHelpGrow(Point where); void HandleHelpChoice(short theItem); OSErr OpenHelp(void); void CloseHelp(void); WindowPtr GetHelpWindow(void); void HandleHelpClick(Point where); Boolean HandleHelpKey(uchar theChar, uchar theKey); void HandleHelpActivate(Boolean nowActive); void GetHelpText(short theSect); void ResizeHelp(Rect *newRect); void UpdateHelp(void); void UpdateHelpScroll(short oldValue, short newValue); pascal void HelpScrollAction(ControlHandle theControl, short thePart); void DoHelpHelp(Point globalPt); #endif \ No newline at end of file diff --git a/Headers/ImageUtils.h b/Headers/ImageUtils.h new file mode 100644 index 0000000..875edc5 --- /dev/null +++ b/Headers/ImageUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __IMAGEUTILS__ #define __IMAGEUTILS__ #include "MonitorUtils.h" enum { ifSelected = 0x00000001L, // if ==> image->flags constants ifSelVisible = 0x00000002L, ifCropped = 0x00000004L, ifBanded = 0x00000008L, ifCorrupt = 0x00000010L, ifAborted = 0x00000020L, ifFull = 0x00000040L, ifDithered = 0x00000080L, ifNeedsWhiteBG = 0x00000100L, ifNoOnscreenProg = 0x00000200L, ifGWOrigSize = 0x00000400L, ifScreenSize = 0x00000800L, ifFilename = 0x00001000L, ifIsAboutBox = 0x00002000L, ifCommentsClosed = 0x00004000L, ifGWTempMem = 0x00008000L, ifNeedToRedraw = 0x00010000L }; extern void DeferImageUpdate(ImageHandle theImage); extern OSErr UpdateImage(ImageHandle theImage); extern void HandleImageActivate(ImageHandle theImage, Boolean nowActive); extern void HandleImageClick(ImageHandle theImage, EventRecord *theEvent); ImageHandle NewImage(void); void DisposeImage(ImageHandle theImage); ImageHandle CopyImage(ImageHandle srcImage); ImageHandle LastImage(void); ImageHandle PreviousImage(ImageHandle theImage); Boolean AnotherFull(ImageHandle theImage); ImageHandle FindImage(WindowPtr theWindow); void UpdateImages(MonitorHandle theMonitor); void SetUpOnscreenPort(JVDrawParamsHandle theParams, ImageHandle theImage); void SetUpOffscreenPort(JVDrawParamsHandle theParams, ImageHandle theImage); OSErr DrawImage(ImageHandle theImage, short bitsFlags, NestedProgressPtr progProc); OSErr DrawImageGWorld(ImageHandle theImage, short bitsFlags, NestedProgressPtr progProc); OSErr DrawImageFull(ImageHandle theImage, short bitsFlags, NestedProgressPtr progProc); void DrawFullBorder(ImageHandle theImage); void DrawFileName(ImageHandle theImage); Boolean MakeImageGWorld(ImageHandle theImage, Boolean quantizing); void KillGWorld(ImageHandle theImage); CTabHandle GetGWorldColors(ImageHandle theImage, short gwDepth); void DoImageHelp(WindowPtr theWindow, Point globalPt); #define FrontImage() FindImage(FWFrontWindow()) #define WinTitle(image) (*((WindowPeek)(*(image))->window)->titleHandle) #define FileName(image) ((*(image))->file.name) #define Cropped(image) (((*image)->flags & ifCropped) != 0) #define Banded(image) (((*image)->flags & ifBanded) != 0) #define Full(image) (((*image)->flags & ifFull) != 0) #define Dithered(image) (((*image)->flags & ifDithered) != 0) #define Corrupt(image) (((*image)->flags & ifCorrupt) != 0) #define NeedsWhiteBG(image) (((*image)->flags & ifNeedsWhiteBG) != 0) #define NoOnscreenProg(image) (((*image)->flags & ifNoOnscreenProg) != 0) #define GWOrigSize(image) (((*image)->flags & ifGWOrigSize) != 0) #define ScreenSize(image) (((*image)->flags & ifScreenSize) != 0) #define ShowFilename(image) (((*image)->flags & ifFilename) != 0) #define Aborted(image) (((*image)->flags & ifAborted) != 0) #define IsAboutBox(image) (((*image)->flags & ifIsAboutBox) != 0) #define CommentsClosed(image) (((*image)->flags & ifCommentsClosed) != 0) #define GWTempMem(image) (((*image)->flags & ifGWTempMem) != 0) #define NeedToRedraw(image) (((*image)->flags & ifNeedToRedraw) != 0) #endif \ No newline at end of file diff --git a/Headers/JPEG.h b/Headers/JPEG.h new file mode 100644 index 0000000..3442466 --- /dev/null +++ b/Headers/JPEG.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __JPEG__ #define __JPEG__ #include #include #include #include #include #include "JPEGViewTypes.h" extern Boolean VerifyJPEGData(uchar *theData, long theSize); extern Boolean idJPEG(uchar *theData, long theSize, short refNum, FSSpec *theSpec); extern OSErr OpenJPEG(ImageHandle theImage); extern OSErr DrawJPEG(Handle theHandle, JVDrawParamsHandle theParams); extern OSErr FixJPEG(ImageHandle theImage, Handle *finalData, Boolean palette); extern OSErr SaveJPEG(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle privates); extern void ExtractComments(Ptr theJPEG, long origLen, Handle *theComments); extern Handle UnwrapJPEG(Handle srcHandle); extern Handle WrapJPEG(Handle srcHandle, short depth); #endif \ No newline at end of file diff --git a/Headers/JPEGNoQuickTime.h b/Headers/JPEGNoQuickTime.h new file mode 100644 index 0000000..fe2afe7 --- /dev/null +++ b/Headers/JPEGNoQuickTime.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __JPEGNOQUICKTIME__ #define __JPEGNOQUICKTIME__ #include #include "JPEGViewTypes.h" extern OSErr DrawJPEGNoQuickTime(Handle theHandle, JVDrawParamsHandle theParams); #endif \ No newline at end of file diff --git a/Headers/JPEGView.h b/Headers/JPEGView.h new file mode 100644 index 0000000..87843a6 --- /dev/null +++ b/Headers/JPEGView.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ /* * JPEGView header file, to be #included with every JPEGView code segment * * Contains (in order): * Constants (#defines and enums) * In-line functions (#defines) * Typedefs * Structures * Function and Variable Prototypes * */ // Make sure we don't include any unnecessary glue #define SystemSevenOrLater 1 #if THINK_C #define applec 1 #endif // Standard Mac includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // JPEGView resource definitions #include "JPEGView.r.h" /*** Compile-time constants ***/ #ifndef USE_ASM #if defined(powerc) || defined (__powerc) #define USE_ASM 0 #else #define USE_ASM 1 #endif #endif /*** General constants ***/ enum { kStackSize = 48L * 1024L, kMaxPorts = 100, kDialogClose = 0x7acd, kDialogCancel = 0x7ace, kDialogOK = 0x7acf, kCodeResource = 'CODE', kPictResource = 'PICT', kBSChar = 0x08, kTabChar = 0x09, kHelpChar = 0x05, kReturnChar = 0x0d, kEnterChar = 0x03, kEscapeChar = 0x1b, kHomeChar = 0x01, kEndChar = 0x04, kPageUpChar = 0x0b, kPageDownChar = 0x0c, kLeftArrowChar = 0x1c, kRightArrowChar = 0x1d, kUpArrowChar = 0x1e, kDownArrowChar = 0x1f, kClockFreq = 60, kSelRectSpeed = 5, kUpdateDelay = 300, kSleepTime = kSelRectSpeed, kMinSelection = 16, kHeaderSize = 512, kImageID = 'Im', kTitleBarHeight = 19, kFloatingTitleBarHeight = 11, kWindowStepDown = kTitleBarHeight - 1, kWindowStepRight = kTitleBarHeight - 1, kWindowBorderWidth = 6, kWindowBorderHeight = 5, kFileFormats = 8, kInvalidType = -1, kNumStrings = strLast, kNumCursors = rLastSpin - rFirstSpin + 1, kSpinFrequency = 6, kSpinContinue = kNumCursors, errNotADirectory = -31111, errBadJPEG = -31112, codecProgressUpdateScaling = -1, codecProgressUpdateDithering = -2, codecProgressStartAdjust = -3, codecProgressStopAdjust = -4, codecProgressRealOpen = -5, codecProgressRealClose = -6 }; /*** State constants ***/ enum { bfOffscreen = 0x0001, // bf ==> gBitsFlags constants bfOnscreen = 0x0002, bfQuantize = 0x0004, bfUseSlideProgress = 0x0008, bfForceFull = 0x0010 }; enum { plNone, // pl ==> Palettes plSys, plGrey, plImage, plQuant }; enum { ofNever, // of ==> Open Full Screen Options ofAlways, ofAsk, ofNoMatterWhat }; enum { osDeepest, // os ==> Open Screen options osLargest, osMain }; enum { otSame, // ot ==> Open Statistics options otMain }; enum { swNone, // su ==> Startup Options swOpen, swSlide, swAutoSlide }; enum { aqAlways, // aq ==> autoQuantize options aqOnly, aqNever }; enum { sqAlways, // sq ==> saveQuantize options sqOnly, sqNever }; enum { ubAlways, // ub ==> useBitmaps options ubOptional, ubNever }; enum { iqVHigh, // iq ==> imageQuality options iqHigh, iqMedium, iqLow }; enum { bgMaximal, // bg ==> backgroundTime options bgReasonable, bgMinimal }; enum { // is ==> iconStyle options isSquare = 1, isSquareDog = 2, isProportional = 3, isProportionalDog = 4 }; /* * Typedefs */ #include "JPEGViewTypes.h" /**************************************** Main ****************************************/ extern void main(void); extern void StartSpinning(void); extern void StopSpinning(CursPtr newCursor); extern void KeepSpinning(void); extern void SpinIndef(void); extern void HandleAEError(OSErr theErr, short memErr, StringPtr theString); extern void MinorError(short theErr); extern void FatalError(short theErr); extern void StringError(short theErr, StringPtr origString); extern void RequestForeground(void); #include "EventHandlers.h" #include "EventUtils.h" #include "FloatingWindows.h" #include "JPEGViewGlobals.h" #include "MemoryUtils.h" #include "AppleMenu.h" #include "ColorsMenu.h" #include "EditMenu.h" #include "FileMenu.h" #include "GeneralMenus.h" #include "HelpMenu.h" #include "MercutioAPI.h" #include "ViewMenu.h" #include "WindowMenu.h" #include "CompressedResource.h" #include "DialogUtils.h" #include "ImageUtils.h" #include "MarchingAnts.h" #include "MiscellaneousUtils.h" #include "MonitorUtils.h" #include "ProgressProcs.h" #include "QuickDrawUtils.h" #include "StandardFolder.h" #include "WindowUtils.h" #include "Bottlenecks.h" #include "CustomCopyBits.h" #include "BMP.h" #include "GIF.h" #include "JPEG.h" #include "JPEGNoQuickTime.h" #include "PICT.h" #include "PNTG.h" #include "SCRN.h" #include "TIFF.h" #include "QDxDispatchPatch.h" #include "Quantize.h" #include "ColorsWindow.h" #include "CommentsWindow.h" #include "Preferences.h" #include "SaveOpen.h" #include "SlideControlsWindow.h" #include "SlideShow.h" #include "SlideShowOptions.h" #include "StatisticsWindow.h" #include "AppleEventUtils.h" #include "CoreEventHandlers.h" #include "JPEGViewEventHandlers.h" #include "RequiredEventHandlers.h" #include "SendAppleEvents.h" #include "cApplication.h" #include "cDocument.h" #include "cDrawingArea.h" #include "cFile.h" #include "cImage.h" #include "cPixelMap.h" #include "cSelection.h" #include "cWindow.h" #if applec #pragma dump ":Headers:MPW.Header" #endif \ No newline at end of file diff --git a/Headers/JPEGView.h.o b/Headers/JPEGView.h.o new file mode 100644 index 0000000000000000000000000000000000000000..558fcd0b3b50e679641329d3e88b9e55973942b1 GIT binary patch literal 22 dcmZQ%WME=uVBmKSOD!t4HP$oMGh$$30019}11$gm literal 0 HcmV?d00001 diff --git a/Headers/JPEGView.r.h b/Headers/JPEGView.r.h new file mode 100644 index 0000000..64836ac --- /dev/null +++ b/Headers/JPEGView.r.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ /* * JPEGView resource header file, to be #included with every JPEGView code * segment and with the resource definition file */ /* General defines */ #define kVersion 0x0330 #define kPrefsVersion 0x0332 #define kCreator 'JVWR' #define kDarksideCreator 'DSOM' #define kPrefsPrintType 'Prnt' #define kPrefsAliasType 'Alis' #define kPrefsSlideType 'Slid' #define kPatchType 'xPAT' #define rQDxDispatchPatch 128 #define rCustomIcon -16455 #define windoidProc 2048 #define windoidZoomProc 2048 + 8 #define customMenuProc 1 #define option condense #define shift extend /* AppleEvent suites */ #define kJPEGViewSuite kCreator /* AppleEvent classes */ #define cImage 'imag' /* AppleEvent events */ #define kAESlideShow 'Jssh' #define kAEQuantizeImage 'Jqim' /* AppleEvent properties: cImages */ #define pComments 'Jcom' #define pCompression 'Jcmp' #define pDisplayTime 'Jdti' #define pHasImageColorTable 'Jhct' #define pHasQuantColorTable 'Jhqt' #define pImageColorTable 'Jimc' #define pImageFormat 'Jimf' #define pIsAborted 'Jabt' #define pIsBanded 'Jban' #define pIsCompressed 'Jicp' #define pIsCorrupt 'Jcor' #define pIsCropped 'Jcrp' #define pLength 'Jlgh' #define pOriginalBounds 'Jobd' #define pQuantColorTable 'Jquc' #define pQuantTime 'Jqti' /* AppleEvent properties: cDrawingAreas */ #define pDrawQuality 'Jdrq' #define pPalette 'Jpal' /* AppleEvent properties: cWindows */ #define pFullScreen 'Jful' #define pWindowType 'Jwty' /* AppleEvent parameter keys: Quantize Image */ #define keyColorCount 'Jcct' /* AppleEvent parameter keys: Close */ #define keyRestoreColors 'Jrcl' /* AppleEvent parameter keys: Open Documents */ #define keyAutoComments 'Jacm' #define keyAutoExpand 'Jaex' #define keyChangeCreator 'Jccr' #define keyFixTypes 'Jfix' #define keyNoErrors 'Jner' #define keyOpenScreen 'Josc' #define keyOpenFull 'Jofl' #define keyOpenPalette 'Jopl' #define keyOpenQuality 'Joql' #define keyOpenBitmaps 'Jobm' #define keyVisible 'Jvis' /* AppleEvent parameter keys: Save */ #define keyCreatePreview 'Jcpv' #define keyCropWhat 'Jccw' #define keyMakeIcons 'Jmic' #define keySaveQuant 'Jsqu' /* AppleEvent parameter keys: Slide Show */ #define keyDelay 'Jdel' #define keyFilenames 'Jfnm' #define keyFromDisk 'Jdsk' #define keyHideControls 'Jhcl' #define keyHideWindoids 'Jhwo' #define keyIgnoreErrors 'Jige' #define keyImportFiles 'Jimp' #define keyOffscreen 'Joff' #define keyRandom 'Jrnd' #define keyRepeat 'Jrpt' #define keyScanRecursive 'Jrcv' #define keyScreenSaver 'Jssv' #define keyUserControl 'Jucl' /* AppleEvent enumeration extensions */ #define kAEQDDitherCopy 'Jdth' #define enumDrawQuality 'Jdrq' #define kAEDQVeryHigh 'Jvhi' #define kAEDQHigh 'Jhi ' #define kAEDQNormal 'Jnor' #define enumOpenScreen 'Josc' #define kAEOSDeepestColor 'Jdcl' #define kAEOSDeepestGray 'Jdgy' #define kAEOSLargestColor 'Jlcl' #define kAEOSLargestGray 'Jlgy' #define kAEOSMain 'Jmai' #define enumOpenFull 'Jofl' #define kAEOFAlways 'Jalw' #define kAEOFAlwaysIfLarge 'Jall' #define kAEOFAskIfLarge 'Jakl' #define kAEOFNever 'Jnvr' #define enumOpenPalette 'Jopl' #define kAEOPQuantImageScrn 'Jqis' #define kAEOPImageQuantScrn 'Jiqs' #define kAEOPQuantScrn 'Jqs ' #define kAEOPImageScrn 'Jis ' #define kAEOPScrn 'Jsoy' #define enumPalette 'Jpal' #define kAEPSystem 'Jsys' #define kAEPGrayscale 'Jgry' #define kAEPImage 'Jimg' #define kAEPQuantized 'Jquz' #define enumWindowType 'Jwty' #define kAEWTStatistics 'Jstw' #define kAEWTComments 'Jcmw' #define kAEWTColors 'Jclw' #define kAEWTHelp 'Jhlw' #define kAEWTPreferences 'Jprd' #define kAEWTSlideShow 'Jssd' #define kAEWTImage 'Jimw' #define kAEWTFullImage 'Jfiw' #define kAEWTAbout 'Jabt' #define kAEWTSlideControls 'Jscw' #define kAEWTAboutHelp 'Jahw' /* Window and Dialog IDs */ #define kSlideShowDialogID kAEWTSlideShow #define kSlideControlsWindowID kAEWTSlideControls #define kPrefsDialogID kAEWTPreferences #define kStatWindowID kAEWTStatistics #define kCommentsWindowID kAEWTComments #define kColorsWindowID kAEWTColors #define kHelpWindowID kAEWTHelp #define kImageWindowID kAEWTImage #define kFImageWindowID kAEWTFullImage #define kAboutWindowID kAEWTAbout #define kAboutHelpDialogID kAEWTAboutHelp #define kAboutDialogID 'Jabd' #define kProgressDialogID 'Jpgd' #define kOpenDialogID 'Jopd' #define kSaveDialogID 'Jsvd' #define kFolderDialogID 'Jfld' #define kNoCompression 0 #define kCCITTCompression 'CIT3' #define kPackBitsCompression 'PACK' #define kLZWCompression 'LZW ' #define kJPEGCompression 'jpeg' #define kVideoCompression 'rpza' #define kAnimationCompression 'rle ' #define kRawCompression 'raw ' #define kGraphicsCompression 'smc ' #define kCinepackCompression 'cdvc' #define kRLE4Compression 'RLE4' #define kRLE8Compression 'RLE8' /* File types */ #define kPrefsType 'pref' #define kAPPLType 'APPL' #define kPICTType 'PICT' #define kJFIFType 'JFIF' #define kJPEGType 'JPEG' #define kHelpType 'HLP!' #define kGIFType 'GIFf' #define kTIFFType 'TIFF' #define kAllTypes '****' #define kSCRNType 'SCRN' #define kBMPType 'BMPp' #define kPNTGType 'PNTG' /* FREF/BNDL/JVWR resources */ #define rAPPLType 128 #define rPICTType 129 #define rJFIFType 130 #define rJPEGType 131 #define rHelpType 132 #define rGIFType 133 #define rAllTypes 134 #define rTIFFType 135 #define rBMPType 136 #define rSCRNType 137 #define rPNTGType 138 #define rAPPLID 0 #define rPICTID 1 #define rJFIFID 2 #define rJPEGID 3 #define rHelpID 4 #define rGIFID 5 #define rAllID 6 #define rTIFFID 7 #define rBMPID 8 #define rSCRNID 9 #define rPNTGID 10 #define rBNDLRsrc 128 #define rJVWRRsrc 0 #define rStandardButton 1000 #define rDepressedButton 2000 #define rDisabledButton 3000 #define rForwardButton 0 #define rStopButton 1 #define rPauseButton 2 #define rReverseButton 3 #define rDoubleForwardButton 4 #define rDoubleReverseButton 5 /* WIND/wctb resources */ #define rStatWindow 128 #define rCommentsWindow 129 #define rColorsWindow 130 #define rSlideControlsWindow 131 #define rImageWindow 132 #define rFullImageWindow 133 #define rHelpWindow 134 #define rAboutImageWindow 135 #define rAboutBox 384 /* STR# resources */ #define rFatalErrors 128 #define rMinorErrors 129 #define rStringErrors 130 #define rGenericStringErrors 131 #define rStrings 132 #define rFormatNames 133 /* MBAR resources */ #define rMenuBar 128 /* MENU resources */ #define rIconMenu 119 #define rCropMenu 120 #define rSaveMenu 121 #define rSlideControlMenu 122 #define rSlideSourceMenu 123 #define rTimeMenu 124 #define rQualityMenuID "\0x7d" #define rQualityMenu 125 #define rPrefsMenu 126 #define rHelpMenu 127 #define rAppleMenu 128 #define rFileMenu 129 #define rEditMenu 130 #define rViewMenu 131 #define rColorsMenu 132 #define rWindowMenu 133 /* DITL resources */ #define rOpenDialog 129 #define rSaveDialog 130 #define rFolderDialog 131 #define rSlideShowDialog 133 #define rPrefsDialog 134 #define rProgressDialog 135 #define rAboutHelpDialog 136 #define rModalProgressDialog 137 #define rOpenDialogNoQT 138 #define rSimpleSaveDialog 139 #define rMinorAlert 256 #define rFatalAlert 257 #define rUnknownAlert 258 #define rAbortSlidesAlert 260 #define rEndSlidesAlert 261 #define rSlideMemAlert 262 #define rTooBigAlert 263 #define rBadJPEGAlert 264 #define rNeeds68020Alert 265 #define rNeedsSystem7Alert 266 #define rPowerPCAlert 9876 /* CTRL resources */ #define rPrefsMenuControl 128 #define rHelpMenuControl 129 #define rHelpScrollControl 130 #define rTimeMenuControl 131 #define rSlideControlMenuControl 132 #define rSlideSourceMenuControl 133 #define rSavePopupControl 134 #define rCropPopupControl 135 #define rIconPopupControl 136 /* CURS resources */ #define rHandCursor 128 #define rFirstSpin 129 #define rLastSpin 156 #define rSizeCursor 157 /* ICON resources */ #define rAPPLIcon 128 #define rPICTIcon 129 #define rOtherIcon 130 #define rJPEGIcon 131 #define rHelpIcon 132 #define rGIFIcon 133 #define rTIFFIcon 134 #define rBMPIcon 135 #define rSCRNIcon 136 #define rPNTGIcon 137 /* PICT resources */ #define rAboutPict 128 #define rAboutHelpPict 129 /* TEXT/styl resoources */ #define kHelpTextBase 128 #define rCreditsText 300 /*** Error constants ***/ #define errNoMemory 1 #define errNoLoadCode 2 #define errNoLoadStrings 3 #define errNoLoadCursor 4 #define errNoSystem7 5 #define errNoLoadCLUT 6 #define errNoMenu 7 #define errNoAppleEvents 8 #define errNoDeviceInfo 9 #define errFunnyQTVersion 2 #define errNoAboutDialog 3 #define errNoAESend 4 #define errNoHelp 5 #define errNoPrefsDialog 6 #define errCantWritePrefs 7 #define errNoImagesFound 8 #define errNoSlideDialog 9 #define errCantAddPreview 10 #define errNoPrinterSelected 11 #define errNoHelpFound 12 #define errCorruptImage 1 #define errInvalidFile 2 #define errCantOpenFile 3 #define errNoDrawMemory 4 #define errNoLoadMemory 5 #define errCantReadFile 6 #define errCantWriteFile 7 #define errCantCreateFile 8 #define errNoUnwrapMemory 9 #define errNoWrapMemory 10 #define errCantOpenWindow 11 #define errNoOffscreenMemory 12 #define errNoQuantMemory 13 #define errCantMakePreview 14 #define errNoColorsMemory 15 #define errCantCreateIcons 16 #define errNoCropMemory 17 #define errNoSaveMemory 18 #define errHSIFile 19 #define errNoPrintMemory 20 #define errCantPrint 21 #define errNoCopyMemory 22 #define errBadTIFFExtension 23 #define errNoQuickTime 24 #define errJPEGError 25 #define errBinHexData 26 #define errUUEncodeData 27 /*** String constants ***/ #define strFileName 0 #define strImageSize 1 #define strImageColors 2 #define strImageStatus 3 #define strCompression 4 #define strFileFormat 5 #define strImageLength 6 #define strDisplayedSize 7 #define strDisplayedColors 8 #define strDisplayQuality 9 #define strDisplayTime 10 #define strOffscreenBitmap 11 #define strFreeMemory 12 #define strImageSize1 13 #define strImageSize2 14 #define strImageColors1 15 #define strImageColors2 16 #define strNormal 17 #define strAborted 18 #define strBanded 19 #define strCropped 20 #define strCorrupt 21 #define strLZWGIF 22 #define strAdobeJPEG 23 #define strQuickTimeJPEG 24 #define strQuality 25 #define strIJGJPEG 26 #define strUnknownJPEG 27 #define strUncompressed 28 #define strPICT 29 #define strJPEG 30 #define strGIF 31 #define strImageLength1 32 #define strImageLength2 33 #define strImageLength3 34 #define strDisplayedSize1 35 #define strDisplayedSize2 36 #define strDisplayedSize3 37 #define strDisplayedColors1 38 #define strDisplayedColors2 39 #define strSystemColors1 40 #define strGrayscales1 41 #define strImageColorsX1 42 #define strReducedColors1 43 #define strSystemColors2 44 #define strGrayscales2 45 #define strImageColorsX2 46 #define strReducedColors2 47 #define strVeryHigh 48 #define strHigh 49 #define strNormalQ 50 #define strNA 51 #define strDisplayTime1 52 #define strNoBitmap 53 #define strOffscreenBitmap1 54 #define strOffscreenBitmap2 55 #define strFreeMemory1 56 #define strSummary1 57 #define strThousands 58 #define strMillions 59 #define strJPEGView 60 #define strJPEGViewHelp 61 #define strJPEGViewPICT 62 #define strJPEGViewPrefs 63 #define strJPEGViewTempFile 64 #define strSelect 65 #define strDesktop 66 #define strDecompressing 67 #define strDithering 68 #define strScaling 69 #define strReducingTo 70 #define strCreatingPreview 71 #define strCreatingIcons 72 #define strCreatingPreviewIcons 73 #define strSaving 74 #define strNagMessages 75 // thru 86 #define strNoComments 87 #define strRestart 88 #define strResume 89 #define strShowStatistics 90 #define strHideStatistics 91 #define strShowComments 92 #define strHideComments 93 #define strShowColors 94 #define strHideColors 95 #define strBeginSlideShow 96 #define strResumeSlideShow 97 #define strSSNone 98 #define strAboutJPEGView 99 #define strVersionPPC 100 #define strVersion68k 101 #define strSlideLoading 102 #define strSlideReducing 103 #define strSlideDrawing 104 #define strSlideReady 105 #define strSlidePaused 106 #define strSlideDelaying 107 #define strSlideRendering 108 #define strScanningDirectory 109 #define strPrinting 110 #define strCopying 111 #define strPreparing 112 #define strCCITT3 113 #define strPackBits 114 #define strLZW 115 #define strRLE4 116 #define strRLE8 117 #define strLZWPredict 118 #define strHelpFile 119 #define strLast 120 /*** Slide control menu constants ***/ #define slideControlUserItem 1 #define slideControlAutoItem 2 /*** Slide source menu constants ***/ #define slideSourceMemoryItem 1 #define slideSourceDiskItem 2 /*** Time menu constants ***/ #define timeSeconds 1 #define timeMinutes 2 #define timeHours 3 /*** Quality menu constants ***/ #define qualityVHighItem 1 #define qualityHighItem 2 #define qualityMediumItem 3 /*** Prefs menu constants ***/ #define prefsWindows 1 #define prefsDisplay 2 #define prefsOffscreen 3 #define prefsFiles 4 #define prefsStartup 5 /*** Apple menu constants ***/ #define appleAboutItem 1 #define appleAboutHelpItem 2 /*** File menu constants ***/ #define fileOpenItem 1 #define fileImportItem 2 #define fileCloseItem 3 #define fileCloseAllItem 4 #define fileSaveItem 6 #define fileSlideItem 8 #define fileStartSlideItem 9 #define fileEndSlideItem 10 #define filePageSetupItem 12 #define filePrintItem 13 #define filePrefsItem 15 #define fileQuitItem 17 /*** Edit menu constants ***/ #define editUndoItem 1 #define editCutItem 3 #define editCopyItem 4 #define editPasteItem 5 #define editClearItem 6 #define editSelectScreenItem 8 #define editCropItem 10 #define editUncropItem 11 /*** View menu constants ***/ #define viewFullScreenItem 1 #define viewResizeItem 3 #define viewNormalItem 5 #define viewHalfItem 6 #define viewDoubleItem 7 #define viewMaxItem 8 #define viewShrinkItem 10 #define viewExpandItem 11 /*** Color menu constants ***/ #define colorSysItem 1 #define colorGrayItem 2 #define colorImageItem 3 #define colorQuantItem 4 #define colorDitherItem 6 #define colorQualityItem 8 /*** Window menu constants ***/ #define windowStatItem 1 #define windowCommentsItem 2 #define windowColorsItem 3 #define windowPreviousItem 5 #define windowNextItem 6 #define windowFirstItem 8 /*** About dialog constants ***/ #define aboutUserItem 1 #define aboutLineUser 4 /*** Open dialog constants ***/ #define openScanButton 16 /*** Save dialog constants ***/ #define saveCloseBox 13 #define saveLineUser1 14 #define savePopupMenu 15 #define saveLineUser2 16 #define saveIconsBox 17 #define savePreviewBox 18 #define savePaletteBox 19 #define saveLineUser3 20 #define saveCropMenu 21 /*** Select folder dialog constants ***/ #define folderSelectButton 13 /*** Help dialog constants ***/ #define helpPopUpMenu 1 #define helpTextArea 2 #define helpScrollBar 3 /*** Slide show dialog constants ***/ #define slideBeginButton 1 #define slideOutlineUser 2 #define slideRevertButton 3 #define slideDelayText 4 #define slideDelayEdit 5 #define slideTimePopUpMenu 6 #define slideRandomBox 7 #define slideRepeatBox 8 #define slideIgnoreErrBox 9 #define slideHideWindoidsBox 10 #define slideHideControlsBox 11 #define slideAutoCommentsBox 12 #define slideFilenamesBox 13 #define slideControlMenu 14 #define slideLeftBoxUser 15 #define slideSelectButton 16 #define slideFolderUser 17 #define slideRecursiveBox 18 #define slideImportBox 19 #define slideOffscreenBox 20 #define slideSourceMenu 21 #define slideRightBoxUser 22 /*** Preferences dialog constants ***/ #define prefsFirstWindowsItem 1 #define prefsImageDeepestButton 2 #define prefsImageLargestButton 3 #define prefsImageMainButton 4 #define prefsUseColorBox 5 #define prefsAlwaysFullButton 7 #define prefsAlwaysLargeButton 8 #define prefsAskLargeButton 9 #define prefsNeverFullButton 10 #define prefsExpandSmallBox 11 #define prefsOnlyOneBox 12 #define prefsLastWindowsItem 12 #define prefsFirstDisplayItem 13 #define prefsVHighQualityButton 14 #define prefsHighQualityButton 15 #define prefsMedQualityButton 16 #define prefsBackgroundBox 17 #define prefsQuantizeAlwaysButton 19 #define prefsQuantizeOnlyButton 20 #define prefsQuantizeNeverButton 21 #define prefsDitherQuantizedBox 22 #define prefsUsePaletteBox 23 #define prefsRestoreColorsBox 24 #define prefsLastDisplayItem 24 #define prefsFirstBitmapsItem 25 #define prefsBitmapsAlwaysButton 26 #define prefsBitmapsOptionalButton 27 #define prefsBitmapsNeverButton 28 #define prefsOriginalSizeBox 29 #define prefsNoUncompressedBox 30 #define prefsLastBitmapsItem 30 #define prefsFirstFilesItem 31 #define prefsFixFilesBox 31 #define prefsFixCreatorsBox 32 #define prefsSaveQAlwaysButton 34 #define prefsSaveQOnlyButton 35 #define prefsSaveQNeverButton 36 #define prefsDefaultPICTBox 37 #define prefsSavePreviewsBox 38 #define prefsCompressPreviewsBox 39 #define prefsAddIconsBox 40 #define prefsIconStyleMenu 41 #define prefsLastFilesItem 41 #define prefsFirstMiscItem 42 #define prefsBeginSlidesButton 43 #define prefsSlideDialogButton 44 #define prefsOpenDialogButton 45 #define prefsNothingButton 46 #define prefsAutoCommentsBox 47 #define prefsMaximalBox 49 #define prefsReasonableBox 50 #define prefsMinimalBox 51 #define prefsUseQuickTimeBox 52 #define prefsLastMiscItem 52 #define prefsPopUpMenu 53 #define prefsBoxUser 54 /*** Progress dialog constants ***/ #define progressText 1 #define progressUser 2 #define progressCancel 3 #define progressText2 4 /*** End slide show alert constants ***/ #define endSSContinue 1 #define endSSAbort 2 #define endSSOptions 3 /* General resource defines */ #define rNil "" #define hmnuBlankItem HMStringItem { rNil, rNil, rNil, rNil } #define hdlgBlankItem HMStringItem { { 0, 0 }, { 0, 0, 0, 0 }, rNil, rNil, rNil, rNil } #define res9 reserved, reserved, reserved, reserved, reserved, reserved, reserved, \ reserved, reserved #define res12 reserved, reserved, reserved, reserved, reserved, reserved, reserved, \ reserved, reserved, reserved, reserved, reserved #define res13 reserved, reserved, reserved, reserved, reserved, reserved, reserved, \ reserved, reserved, reserved, reserved, reserved, reserved \ No newline at end of file diff --git a/Headers/JPEGViewEventHandlers.h b/Headers/JPEGViewEventHandlers.h new file mode 100644 index 0000000..279629c --- /dev/null +++ b/Headers/JPEGViewEventHandlers.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __JPEGVIEWEVENTHANDLERS__ #define __JPEGVIEWEVENTHANDLERS__ extern pascal OSErr HandleQuantize(AppleEvent *theEvent, AppleEvent *reply, long refCon); extern pascal OSErr HandleSlideShow(AppleEvent *theEvent, AppleEvent *reply, long refCon); extern pascal OSErr HandleCopy(AppleEvent *theEvent, AppleEvent *reply, long refCon); extern OSErr DoCopy(void); extern OSErr GetSelectedPICT(ImageHandle theImage, PicHandle *thePicture); extern OSErr DoSlideShow(void); #endif \ No newline at end of file diff --git a/Headers/JPEGViewGlobals.h b/Headers/JPEGViewGlobals.h new file mode 100644 index 0000000..85f0fb7 --- /dev/null +++ b/Headers/JPEGViewGlobals.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __GLOBALS__ #define __GLOBALS__ #include #include #include #include #include #include #include #include #include "JPEGViewTypes.h" #include "Preferences.h" #include "SlideShow.h" extern AEIdleUPP gAEIdleProc; extern ICMProgressUPP gGenericProgress, gSlideProgress, gDrawProgress; extern UserItemUPP gOutlineOK, gPopUpMenuBox, gLineItem; extern ModalFilterUPP gGenericFilter; extern ModalFilterYDUPP gOpenSaveModalFilter; #if defined(powerc) || defined(__powerc) extern QDGlobals qd; #endif extern NMRec gTheNotification; extern THPrint gPrintRecord; extern Boolean gInAppleEvent, gInBackground, gDone, gMenuVisible, gMenuEnabled, gCommentsOpen, gGetAbout, gHidden, gScreenSaver, gSlideFolderValid, gFoundOSL, gDragMgrPresent, gHelpFound; extern PrefsData gThePrefs; extern SlideOptionsHandle gSlideOptions; extern SlideOptions gDefaultSlideOptions; extern OSType gImageType[kFileFormats]; extern ImageFormatPtr gFormat[kFileFormats]; extern ImageFormat gPICTFormat; extern RGBColor gBlack, gWhite, gFGrey; extern ImageHandle gImageRoot, gDrawing; extern MonitorHandle gMainMonitor; extern MenuHandle gAppleMenu; extern CursHandle gCross, gHand, gSize; extern PaletteHandle gColorPalette[], gGreyPalette[]; extern DialogRecord *gPortPool; extern GWorldPtr gGenericGWorld, gPreviewGWorld, gIconGWorld; extern CodecInfo gJPEGInfo; extern PrefsData gOldPrefs; extern StringPtr gString[kNumStrings], gNullString; extern NestedProgress gDummyProg; extern Point gScreenSaverPoint; extern Handle gIconSuite; extern long gQTVersion, gBadWindowID, gMemSlop; extern short gMenuHeight, gTitleBarHeight, gIntError, gPendingButton, gHelpItem; extern short *gErrTable; extern uchar *gScaleTable, gThousandsSep, gDecimal, gListSep; extern char gSlideShow; #endif \ No newline at end of file diff --git a/Headers/JPEGViewPlugIn.h b/Headers/JPEGViewPlugIn.h new file mode 100644 index 0000000..0309f80 --- /dev/null +++ b/Headers/JPEGViewPlugIn.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __JPEGVIEWPLUGIN__ #define __JPEGVIEWPLUGIN__ /* Function descriptions: --------------------------------------------------------------------------------------- plugInAbout: Display the plug-in's about box --> plugInResFile file specification record of the plug-in --> plugInGlobals handle to the plug-in's globals (from plugInOpen) returns: noErr -- initialization was successful memFullErr -- not enough memory to identify the image other errors -- any other problems --------------------------------------------------------------------------------------- plugInInitialize: Initialize the plug in; called once when the plug-in is initialized --> plugInResFile file specification record of the plug-in <-- plugInInfo handle to a plug-in information record <-- plugInGlobals handle to the plug-in's globals returns: noErr -- initialization was successful memFullErr -- not enough memory to initialize the plug-in errInitializeFailed -- initialization failed --------------------------------------------------------------------------------------- plugInIdentify: Attempt to identify the image --> plugInResFile file specification record of the plug-in --> plugInGlobals handle to the plug-in's globals (from plugInOpen) <--> imageData handle to the currently-loaded data; guaranteed to be at least 1024 bytes long; more can be loaded if necessary --> dfRefNum reference number of the file's data fork --> imageFile file specification record of the file returns: noErr -- the image was identified correctly memFullErr -- not enough memory to identify the image errInvalidImage -- the image was not identified other errors -- error reading the file --------------------------------------------------------------------------------------- plugInLoad: Load the image data --> plugInResFile file specification record of the plug-in --> plugInGlobals handle to the plug-in's globals (from plugInOpen) <--> imageData handle to the image data; initially contains data from the data fork --> dfRefNum reference number of the file's data fork --> imageFile file specification record of the file returns: noErr -- the image was loaded successfully memFullErr -- not enough memory to load the image errInvalidImage -- the image was not identified other errors -- error reading the file --------------------------------------------------------------------------------------- plugInOpen: Open the image after loading, by pulling vital information from the data --> plugInResFile file specification record of the plug-in --> plugInGlobals handle to the plug-in's globals (from plugInOpen) <-- imageGlobals handle to the plug-in's globals for this image <-- horizontalDPI horizontal resolution of the image (in DPI) as a Fixed <-- verticalDPI vertical resolution of the image (in DPI) as a Fixed <-- globalRect rectangle, in pixels, of the full-sized image <-- croppedRect rectangle, in pixels, of the initial cropped area <-- imageDepth depth of the image, or 32+depth for grayscale images <-- imageColors handle to a color table containing the image colors, or nil if none <-- compressionType index in the plugInInfo record of the compression info <-- compressionDesc description of the compression (as seen in the stats), or nil to take the description from the plugInInfo <-- imageComments handle to the image's comments returns: noErr -- the image was recognized successfully memFullErr -- not enough memory to open the image errInvalidImage -- an error was found in the image data other errors -- any other problems --------------------------------------------------------------------------------------- plugInDraw: Draw the image to the current port --> plugInResFile file specification record of the plug-in --> plugInGlobals handle to the plug-in's globals (from plugInOpen) --> imageGlobals handle to the plug-in's globals for this image --> imageData handle to the image data --> horizontalDPI horizontal resolution of the image (in DPI) as a Fixed --> verticalDPI vertical resolution of the image (in DPI) as a Fixed --> globalRect rectangle, in pixels, of the full-sized image --> croppedRect rectangle, in pixels, of the initial cropped area --> imageDepth depth of the image, or 32+depth for grayscale images --> imageColors handle to a color table containing the image colors, or nil if none --> compressionType index in the plugInInfo record of the compression info --> imageComments handle to the image's comments --> progressProc a progress procedure record; call this occasionally to update the progress display returns: noErr -- the image was drawn successfully memFullErr -- not enough memory to draw the image errInvalidImage -- an error was found in the image data other errors -- any other problems --------------------------------------------------------------------------------------- plugInConvert: Convert the image to a different format --> plugInResFile file specification record of the plug-in --> plugInGlobals handle to the plug-in's globals (from plugInOpen) --> imageGlobals handle to the plug-in's globals for this image ... (not finished yet) */ typedef unsigned short PlugInFlags; typedef unsigned short CompressionFlags; typedef OSErr PlugInError; typedef struct CompressionInfo { Str31 compressionName; // the name as it should appear in the menu CompressionFlags compressionParams; // the compression support flags } CompressionInfo, *CompressionInfoPtr, **CompressionInfoHandle; typedef struct PlugInInfo { PlugInFlags plugInParams; // the plug-in's parameters short compressionMethods; // the number of compression methods supported CompressionInfo compressionInfo[1]; // list of compression info records } PlugInInfo, *PlugInInfoPtr, **PlugInInfoHandle; typedef struct PlugInData { FSSpec plugInResFile; // file specification of the resource file Handle plugInGlobals; // handle to the plug-in's globals PlugInInfoHandle plugInInfo; // handle to the plug-in information Handle imageData; // handle to the current image data short dfRefNum; // reference number of the file's data fork FSSpec imageFile; // file specification record of the image file Handle imageGlobals; // handle to the plug-in's image globals Fixed horizontalDPI; // horizontal resolution of the image Fixed verticalDPI; // vertical resolution of the image Rect globalRect; // rectangle of the full-sized image Rect croppedRect; // rectangle of the initial cropped area short imageDepth; // depth of the image, or 32+depth for grays CTabHandle imageColors; // handle to the image color table short compressionType; // index in the plugInInfo of compression Str64 compressionDesc; // description of the compression (for stats) Handle imageComments; // handle to the image's comments NestedProgress drawProgress; // the progress function for drawing Handle drawPrivates; // private data structure for drawing } PlugInData, *PlugInDataPtr, **PlugInDataHandle; enum { pifSupportsOpening = 0x0001, // i.e., identify, load, draw pifSupportsConverting = 0x0002, // i.e., convert, save pifSupportsCompressing = 0x0004, // i.e., compress, save pifSupportsPreviews = 0x0008, // should we offer preview option? pifSupportsReducedColors = 0x0010, // should we offer color reduction saving? }; enum { cfCanSaveInMillions = 0x0001, // can we compress in millions of colors? cfCanSaveInThousands = 0x0002, // can we compress in thousands of colors? cfCanSaveIn256Colors = 0x0004, // can we compress in 256 colors? cfCanSaveIn256Grays = 0x0008, // can we compress in 256 grays? }; enum { errInvalidImage = 1, errInitializeFailed = 2, errCantConvert = 3 }; // Examples:JPEG = pifSupportsOpening + pifSupportsSaving + pifSupportsPreviews + // pifSupportsLossyCompression + pifCanSaveInMillions + // pifCanSaveIn256Grays // // PICT = pifSupportsOpening + pifSupportsSaving + pifSupportsPreviews + // pifSupportsReducedColors + pifSupportsLosslessCompression + // pifSupportsLossyCompression + pifSupportsNoCompression + // pifSupportsMultipleCompression + pifCanSaveInMillions + // pifCanSaveInThousands + pifCanSaveIn256Colors + pifCanSaveIn256Grays // // GIF = pifSupportsOpening + pifSupportsSaving + // pifSupportsLosslessCompression + pifCanSaveIn256Colors enum { plugInAbout, plugInInitialize, plugInIdentify, plugInLoad, plugInOpen, plugInDraw, plugInConvert, plugInCompress, plugInSave, plugInClose, plugInQuit }; typedef pascal OSErr (*PlugInDispatcher)(short selector, PlugInDataHandle theData); #endif \ No newline at end of file diff --git a/Headers/JPEGViewTypes.h b/Headers/JPEGViewTypes.h new file mode 100644 index 0000000..af9e0d9 --- /dev/null +++ b/Headers/JPEGViewTypes.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __JPEGVIEWTYPES__ #define __JPEGVIEWTYPES__ #include #include #include #include #include #include #include #include "MarchingAnts.h" typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned long ulong; typedef struct ImageItem ImageItem, *ImagePtr, **ImageHandle; //=================================================================================== // NestedProgress: structure for holding data necessary to do nested progress // procedures. //=================================================================================== typedef struct NestedProgress { ICMProgressProcRecord prog; short level; Fixed begin, end; char aborted; } NestedProgress, *NestedProgressPtr, **NestedProgressHandle; //=================================================================================== // JVPortParams: structure for holding drawing parameters that describe a port. //=================================================================================== typedef struct JVPortParams { CGrafPtr port; // pointer to the port to draw in Rect outer; // bounds of the image, in dest. coordinates Boolean dither; // flag: true to dither when drawing } JVPortParams; //=================================================================================== // JVDrawParams: structs for holding the drawing parameters for a particular drawing // operation, both onscreen and offscreen. //=================================================================================== typedef struct JVDrawParams { struct JVDrawParams **next; // handle to the next in the list Rect bounds; // full-size bounds of image CGrafPtr dummy; // dummy GrafPort for drawing into JVPortParams on; // on-screen drawing parameters JVPortParams off; // off-screen drawing parameters JVPortParams extra; // extra off-screen drawing parameters Boolean quantize; // quantizing flag: true to fill the histogram short quality; // drawing quality to be used Handle privateData; // private data for the plug-in NestedProgress progress; // nested progress procedure record short endprogress; // scan line where we stop drawing progress RgnHandle newupdates; // handle to new updates in the onscreen port PixMapPtr src; // pointer to the source pixmap for DeviceCopy Rect srcrect; // source bounds for DeviceCopy Rect dstrect; // destination bounds for DeviceCopy Rect drawProgressRect; // rectangle used by drawing progress Ptr oldbits; // pointer to the old StdBits routine for FixBits CQDProcs *oldprocs; // pointer to the old set of CQDProcs for FixBits } JVDrawParams, *JVDrawParamsPtr, **JVDrawParamsHandle; typedef Boolean (*idImagePtr)(uchar *theData, long theSize, short refNum, FSSpec *theSpec); typedef OSErr (*OpenImagePtr)(ImageHandle theImage); typedef OSErr (*DrawImagePtr)(Handle theHandle, JVDrawParamsHandle theParams); typedef OSErr (*LoadImagePtr)(short theFile, ImageHandle theImage); typedef OSErr (*SaveImagePtr)(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle privates); typedef OSErr (*FixImagePtr)(ImageHandle theImage, Handle *finalData, Boolean palette); typedef OSErr (*CloneImagePtr)(ImageHandle origImage, ImageHandle newImage); typedef OSErr (*CloseImagePtr)(ImageHandle theImage); typedef pascal void (*StdBitsProcPtr)(PixMap *, Rect *, Rect *, short, RgnHandle); /* * sMonitorItem = linked list item describing a graphics device * */ typedef struct MonitorItem { struct MonitorItem **next; // pointer to the next monitor RgnHandle gray; // this monitor's contribution to the GrayRgn RgnHandle screen; // the full screen area of this monitor GDHandle device; // handle to the original device record short oldres; // old itable resolution Boolean color; // flag: true if monitor has a greyscale CLUT Boolean full; // flag: true if monitor is currently full-screen short depth; // last depth of the monitor Rect rect; // screen rectangle, in global coordinates } MonitorItem, *MonitorPtr, **MonitorHandle; /* * sImageFormat = list of pointers to various actions that need to be performed on * images; used to simply opening/saving [ImageFormat, ImageFormatPtr] */ typedef struct ImageFormat { OSType inType; // the input file type associated with this guy OSType altInType; // alternate input file type OSType outType; // the output file type associated with this guy Boolean customPreviews; // flag: true if this type has different previews Boolean doesColors; // flag: true if the file type can handle quantization Boolean doesBanded; // flag: true if we can save banded images Boolean positiveID; // flag: true if we can make a positive ID Str31 formatName; // string identifying the format idImagePtr id; // identify the image as this type LoadImagePtr load; // read in the data OpenImagePtr open; // initialize the ImageRecord DrawImagePtr draw; // draw to a destination PixMap FixImagePtr fix; // convert PICT or JFIF to this type SaveImagePtr save; // save the data CloneImagePtr clone; // clone the image CloseImagePtr close; // close the image } ImageFormat, *ImageFormatPtr; enum { kStandardQTPreview = false, kCustomPreview = true, kCanSaveQuantization = true, kCantSaveQuantization = false, kCanSaveBanded = true, kCantSaveBanded = false, kIDIsPositive = true, kIDIsPossible = false }; /* * sImageItem = linked list item for images [ImageItem, ImagePtr, ImageHandle] */ struct ImageItem { unsigned short id; // id to flag this as an ImageItem struct ImageItem **next; // pointer to next image record FSSpec file; // file specification of the original image Handle data; // handle to the actual image data Handle comments; // handle to the comments text, if it exists ImageFormatPtr format; // pointer to the appropriate set of procs OSType compression; // type of compression used Str63 compressionDesc; // string description of compression ImageDescription desc; // image descriptor record, for QT images PaletteHandle palette; // current palette for this image PaletteHandle ipalette; // custom palette for this image, if any PaletteHandle qpalette; // quantized palette for this image, if any short npalette; // the numbered palette of the image GWorldPtr gworld; // offscreen copy of the image WindowPtr window; // window record for this image RgnHandle update; // cached update region MonitorHandle dmon; // pointer to the deepest intersecting monitor MonitorHandle smon; // pointer to the shallowest intersecting monitor short quality; // display quality for this image ulong flags; // set of flags describing the image short depth; // depth of the image (1,2,4,8,16,24,32) Rect grect; // greater rectangle of the image (in pixels) Rect qrect; // QuickDraw rectangle (in 72dpi pixels) Rect crect; // cropped image area, relative to grect (in pixels) Rect wrect; // rectangle of this images's window (in screen pixels) AntsReference ants; // reference to our marching ants short num; // number appended to the end long dtime; // last decompressing & display time Handle privateData; // private data for the plug-in }; #endif \ No newline at end of file diff --git a/Headers/MW.Header.68k b/Headers/MW.Header.68k new file mode 100644 index 0000000000000000000000000000000000000000..8960ede2ec5d9e3a6af936eeb1ef3afef2c3b8b8 GIT binary patch literal 392981 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 yy!e-Cavt?+7OzhZ7B1#J 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 literal 0 HcmV?d00001 diff --git a/Headers/MW.Header.PPC b/Headers/MW.Header.PPC new file mode 100644 index 0000000000000000000000000000000000000000..567a679a79e2f8f090cd15a29ded61639b75f6ec GIT binary patch literal 389077 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� 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
    LVYjq7R#xL2^4)In+l>q;QY$Uxu6?m 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 //===================================================================================== // If you are using old headers that don't know about the new Pattern definitions you // may need to uncomment this line. //===================================================================================== //#define dangerousPattern 1 //===================================================================================== // Definition of the AntsRecord; note that there is no need for other functions to know // anything about the internals here. Everything that you will need is provided // through accessor functions which accept parameters of type AntsReference, which is // intended to be an opaque data type. //===================================================================================== typedef struct AntsRecord { GWorldPtr verticalWorld; GWorldPtr horizontalWorld; Rect bounds, limitRect; GrafPtr port; Boolean active; Boolean visible; Boolean drawn; } AntsRecord, *AntsPtr, **AntsHandle; //===================================================================================== // Here is the AntsReference typedef. All ants functions accept AntsReference // parameters. //===================================================================================== typedef AntsHandle AntsReference; //===================================================================================== // Minimum values in each dimension for a "valid" selection. //===================================================================================== enum { antsMinimumX = 8, antsMinimumY = 8 }; //===================================================================================== // The public ants interface. //===================================================================================== #ifdef __cplusplus extern "C" { #endif // NewAnts: allocate and initialize a new set of ants extern AntsReference NewAnts(void); // DisposeAnts: dispose of all memory associated with an ants record extern void DisposeAnts(AntsReference theAnts); // AntsHaveSelection: returns true if there is a non-nil selection extern Boolean AntsHaveSelection(AntsReference theAnts); // ResetAntsSelection: resets the selection to nil extern void ResetAntsSelection(AntsReference theAnts); // GetAntsSelection: returns the bounding rectangle of the current selection extern void GetAntsSelection(AntsReference theAnts, Rect *theBounds); // SetAntsSelection: change the current selection's bounding rectangle extern void SetAntsSelection(AntsReference theAnts, Rect *newBounds); // GetAntsLimitRect: returns the limit rectangle for clipping and mouse tracking extern void GetAntsLimitRect(AntsReference theAnts, Rect *limitRect); // SetAntsLimitRect: sets the limit rectangle for clipping and mouse tracking extern void SetAntsLimitRect(AntsReference theAnts, Rect *newLimit); // GetAntsPort: returns the port used for drawing the ants extern GrafPtr GetAntsPort(AntsReference theAnts); // SetAntsPort: sets the port for ant drawing extern void SetAntsPort(AntsReference theAnts, GrafPtr thePort); // AreAntsVisible: returns true if the ants are currently being shown extern Boolean AreAntsVisible(AntsReference theAnts); // TrackAntsSelection: tracks the mouse as a new selection is made extern void TrackAntsSelection(AntsReference theAnts, Point localStart); // ShowAnts: makes the current ants selection visible extern void ShowAnts(AntsReference theAnts); // HideAnts: hides the current selection, restoring the original background extern void HideAnts(AntsReference theAnts); // AnimateAnts: rotates the dashed rectangle by one notch and redraws it extern void AnimateAnts(AntsReference theAnts); // ActivateAnts: sets up the ants so they display an animated dashed rectangle extern void ActivateAnts(AntsReference theAnts); // DeactivateAnts: sets the ants to display a stable dotted rectangle extern void DeactivateAnts(AntsReference theAnts); #ifdef __cplusplus } #endif #endif \ No newline at end of file diff --git a/Headers/MemoryUtils.h b/Headers/MemoryUtils.h new file mode 100644 index 0000000..4c5fe61 --- /dev/null +++ b/Headers/MemoryUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __MEMORYUTILS__ #define __MEMORYUTILS__ CGrafPtr AllocatePort(void); void DeallocatePort(CGrafPtr thePort); Handle CheckedNewHandle(Size theSize, Boolean canForce); Handle AnyNewHandle(Size theSize); void ClearMem(Ptr thePtr, register Size theSize); long GWorldSize(GWorldPtr theGWorld); long EstGWorldSize(Rect *bounds, short depth); Boolean IsMemAvailable(long request); Boolean MakeMemAvailable(long request); long GetMem(void); pascal long GrowZone(Size cbNeeded); #define AllocateWindow() (WindowPtr)AllocatePort() #define DeallocateWindow(theWindow) DeallocatePort((CGrafPtr)theWindow) #define AllocateDialog() (DialogPtr)AllocatePort() #define DeallocateDialog(theDialog) DeallocatePort((CGrafPtr)theDialog) #endif \ No newline at end of file diff --git a/Headers/MercutioAPI.h b/Headers/MercutioAPI.h new file mode 100644 index 0000000..e19c0a6 --- /dev/null +++ b/Headers/MercutioAPI.h @@ -0,0 +1 @@ +#ifndef __MERCUTIOAPI__ #define __MERCUTIOAPI__ pascal long PowerMenuKey(long theMessage, short theModifiers, MenuHandle hMenu); #endif \ No newline at end of file diff --git a/Headers/MiscellaneousUtils.h b/Headers/MiscellaneousUtils.h new file mode 100644 index 0000000..49bfc59 --- /dev/null +++ b/Headers/MiscellaneousUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __MISCELLANEOUSUTILS__ #define __MISCELLANEOUSUTILS__ Boolean CheckAbort(JVDrawParamsHandle theParams); void StartTimer(void); long StopTimer(void); char *DirName(long dirID, short vRefNum, char *s); OSErr GetDirectoryID(FSSpec *theSpec, long *theID); OSErr GetFullPath(FSSpec *theSpec, Handle *thePath); void ForceFolderUpdate(long dirID, short vRefNum); void AddString(StringPtr theString, StringPtr theAddition); void AddCString(StringPtr theString, char *theAddition, int length); void AddNumber(StringPtr theString, long theNum); void StuffNumber(StringPtr theString, short theItem, long theNum); void StuffNumber0(StringPtr theString, short theItem, long theNum, short theLength); void StuffDepth(StringPtr theString, short theItem, short theDepth); void StuffString(StringPtr theString, short theItem, StringPtr addString); Point GlobalMouse(void); #define abs(val) (((val) < 0) ? -(val) : (val)) #define AddChar(item, c) item[++item[0]] = c #endif \ No newline at end of file diff --git a/Headers/MonitorUtils.h b/Headers/MonitorUtils.h new file mode 100644 index 0000000..ac61777 --- /dev/null +++ b/Headers/MonitorUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __MONITORUTILS__ #define __MONITORUTILS__ void MonitorInit(void); pascal void AddDevice(short depth, short deviceFlags, GDHandle targetDevice, MonitorHandle *theMonitor); MonitorHandle NewMonitor(GDHandle theDevice); MonitorHandle MonitorChanged(void); void SetUpDevices(void); void ResetDevices(void); void ResetColors(void); void FullScreen(MonitorHandle theMonitor); void NormalScreen(MonitorHandle theMonitor); void NudgeWindoids(void); void UnhideMenuBar(void); void RehideMenuBar(void); WindowPtr FrontWindowRgn(RgnHandle theRgn); RgnHandle GetMenuRgn(void); void GetActiveRect(MonitorHandle theMonitor, Rect *theRect); void GetMinMaxMonitor(ImageHandle theImage); MonitorHandle GetDeepMonitor(Boolean pickColor); MonitorHandle GetBigMonitor(Boolean pickColor); MonitorHandle GetImageMonitor(ImageHandle theImage); MonitorHandle GetMostDevice(Rect *theRect); #define PixMapDepth(pm) ((*(pm))->pixelSize) #define MonitorDepth(mon) PixMapDepth((*(*mon)->device)->gdPMap) #define IsColorDevice(device) TestDeviceAttribute(device, gdDevType) #endif \ No newline at end of file diff --git a/Headers/PICT.h b/Headers/PICT.h new file mode 100644 index 0000000..df4518a --- /dev/null +++ b/Headers/PICT.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __PICT__ #define __PICT__ Boolean idPICT(uchar *theData, long theSize, short refNum, FSSpec *theSpec); OSErr OpenPICT(ImageHandle theImage); void GetImageInfo(ImageHandle theImage); OSErr DrawPICT(Handle theHandle, JVDrawParamsHandle theParams); pascal OSErr DrawPICTProgress(short theMessage, Fixed thePercent, ImageHandle theImage); OSErr LoadPICT(short theFile, ImageHandle theImage); OSErr SavePICT(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle privates); OSErr FixPICT(ImageHandle theImage, Handle *finalData, Boolean palette); Handle AddColors(Handle theHandle, ImageHandle theImage); Handle CropPICT(Handle theHandle, ImageHandle theImage); OSErr AddPICTPreview(FSSpec *theFile, GWorldPtr thePreview, Rect *theRect); #endif \ No newline at end of file diff --git a/Headers/PNTG.h b/Headers/PNTG.h new file mode 100644 index 0000000..edc4568 --- /dev/null +++ b/Headers/PNTG.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __PNTG__ #define __PNTG__ extern Boolean idPNTG(uchar *theData, long theSize, short refNum, FSSpec *theSpec); extern OSErr OpenPNTG(ImageHandle theImage); extern OSErr DrawPNTG(Handle theHandle, JVDrawParamsHandle theParams); #endif \ No newline at end of file diff --git a/Headers/Preferences.h b/Headers/Preferences.h new file mode 100644 index 0000000..585682b --- /dev/null +++ b/Headers/Preferences.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __PREFERENCES__ #define __PREFERENCES__ /* * sPrefsData = structure containing all the preferences information [PrefsData] */ #if defined(powerc) || defined(__powerc) #pragma options align=mac68k #endif typedef struct PrefsData { short versionID; // version ID for identifying files short prefsSize; // size of the prefs structure short openScreen; // initial monitor for images Boolean pickColor; // choose color over B&W screens? short openFull; // open images full screen? Boolean expandSmall; // expand small images? Boolean onlyOne; // display only one image at a time? short imageQuality; // display quality for images Boolean updateBack; // background updates? short autoQuant; // quantize images automatically, if appropriate? Boolean ditherQuant; // dither quantized images Boolean imagePalette; // use image palette when available? Boolean restoreColors; // restore colors on last close? short useBitmaps; // use offscreen bitmaps? Boolean origSize; // maintain original-size bitmaps? Boolean noUncomp; // use bitmaps for uncompressed images? Boolean autoFix; // automatically fix file types? Boolean changeCreator; // change creator as well? short saveQuant; // save quantized palettes? Boolean savePICT; // save as PICT by default? Boolean savePrev; // save previews? Boolean compressPrev; // compress previews? Boolean makeIcons; // create custom icons? short iconStyle; // custom icon style short startWith; // startup action Boolean autoComments; // automatically display comments window? short backgroundTime; // amount of time for apps in the background Boolean useQuickTime; // flag: true to use QuickTime for JPEG decompression //-------------------------------------- short helpSection; // last section in the help short prefsSection; // last section in the preferences Boolean statsZoomed; // whether the stats was zoomed last short reminderCount; // count of statistics updates since last reminder //-------------------------------------- Boolean statsOpen; // flag: true if stats was open Boolean commentsOpen; // flag: true if comments was open Boolean colorsOpen; // flag: true if colors was open Rect statsBounds; // statistics window bounds Rect prefsBounds; // preferences dialog bounds Rect slideBounds; // slide show dialog bounds Rect helpBounds; // help window bounds Rect commentsBounds; // comments window bounds Rect colorsBounds; // colors window bounds Rect progressBounds; // progress dialog bounds Rect slideControlsBounds; // slide show controls bounds Rect aboutHelpBounds; // about help dialog bounds } PrefsData; #if defined(powerc) || defined(__powerc) #pragma options align=reset #endif OSErr OpenPrefs(void); void ClosePrefs(void); WindowPtr GetPrefsWindow(void); void HandlePrefsEvent(short theItem); Boolean HandlePrefsKey(char theChar); void HidePrefsItems(short theSect); void ShowPrefsItems(short theSect); void UpdatePrefsButtons(short theSect); Boolean GetPrefsSpec(FSSpec *theSpec); extern void SaveGeneralPrefs(void); extern void LoadGeneralPrefs(void); extern OSErr LoadPrefsHandle(OSType type, short index, Handle *theHandle); extern OSErr SavePrefsHandle(OSType type, short index, Handle theHandle); #endif \ No newline at end of file diff --git a/Headers/ProgressProcs.h b/Headers/ProgressProcs.h new file mode 100644 index 0000000..d238b35 --- /dev/null +++ b/Headers/ProgressProcs.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __PROGRESSPROCS__ #define __PROGRESSPROCS__ extern pascal OSErr DummyProgress(short theMessage, Fixed thePercent, long refCon); extern pascal OSErr GenericProgress(short theMessage, Fixed thePercent, long refCon); extern pascal OSErr DrawProgress(short theMessage, Fixed thePercent, JVDrawParamsHandle theParams); extern pascal OSErr SlideProgress(short theMessage, Fixed thePercent, long refCon); #endif \ No newline at end of file diff --git a/Headers/QDxDispatchPatch.h b/Headers/QDxDispatchPatch.h new file mode 100644 index 0000000..3949e9a --- /dev/null +++ b/Headers/QDxDispatchPatch.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __QDXDISPATCHPATCH__ #define __QDXDISPATCHPATCH__ extern void InstallQDxDispatchPatch(Boolean roundGWorld); extern void RemoveQDxDispatchPatch(void); extern Boolean GetQDxDispatchPatchState(void); extern void SetQDxDispatchPatchState(Boolean on); extern Boolean HasVirtualMemory(void); #endif \ No newline at end of file diff --git a/Headers/Quantize.h b/Headers/Quantize.h new file mode 100644 index 0000000..83ed697 --- /dev/null +++ b/Headers/Quantize.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __QUANTIZE__ #define __QUANTIZE__ extern OSErr DoQuantize(ImageHandle theImage, long numColors, PaletteHandle *thePalette, NestedProgressPtr progProc); extern OSErr QuantizeFromHistogram(Handle theHistogram, long numColors, PaletteHandle *thePalette); extern OSErr ShrinkGWorld(ImageHandle theImage); extern void FillHistogram(PixMapPtr thePixMap); #endif \ No newline at end of file diff --git a/Headers/QuickDrawUtils.h b/Headers/QuickDrawUtils.h new file mode 100644 index 0000000..8fee7d0 --- /dev/null +++ b/Headers/QuickDrawUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __QUICKDRAWUTILS__ #define __QUICKDRAWUTILS__ #define Height(rect) ((rect)->bottom - (rect)->top) #define Width(rect) ((rect)->right - (rect)->left) #define TopLeft(rect) (*(Point *)&(rect).top) #define BotRight(rect) (*(Point *)&(rect).bottom) #define EqualSizeRect(r1, r2) ((Height(r1) == Height(r2)) && (Width(r1) == Width(r2))) #define MySetRect(rect, l, t, r, b) (rect)->left = l, (rect)->top = t, \ (rect)->right = r, (rect)->bottom = b #define MySetPt(point, hp, vp) (point)->h = hp, (point)->v = vp extern void PushPort(void); extern void PopPort(void); extern void MySetPort(CGrafPtr thePort); extern GWorldPtr NewTempGWorld(short width, short height, short depth, CTabHandle colors); extern GWorldPtr MyNewGWorld(Rect *theRect, short theDepth, CTabHandle theColors, GDHandle theDevice, Boolean whiteBack, Boolean inTempMem); extern void MaxRect(Rect *srcRect, Rect *boundingRect, Rect *dstRect); extern void MaxSquare(Rect *srcRect, Rect *squareRect); extern void CopyGWorldToGWorld(GWorldPtr gw1, GWorldPtr gw2, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask); extern void GlobalRect(Rect *theRect, WindowPtr theWindow); extern void GlobalRgn(RgnHandle theRgn, WindowPtr theWindow); extern void LocalRect(Rect *theRect, WindowPtr theWindow); extern void LocalRgn(RgnHandle theRgn, WindowPtr theWindow); extern Boolean Clipped(Rect *theRect, RgnHandle clipRgn); #endif \ No newline at end of file diff --git a/Headers/RequiredEventHandlers.h b/Headers/RequiredEventHandlers.h new file mode 100644 index 0000000..458828f --- /dev/null +++ b/Headers/RequiredEventHandlers.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __REQUIREDEVENTHANDLERS__ #define __REQUIREDEVENTHANDLERS__ pascal OSErr HandleOpenApplication(AppleEvent *theEvent, AppleEvent *reply, long refCon); void GetOpenDefaults(DescType *openScreen, DescType *openFull, DescType *openPalette, DescType *drawQuality); pascal OSErr HandleOpenDocuments(AppleEvent *theEvent, AppleEvent *reply, long refCon); pascal OSErr HandlePrintDocuments(AppleEvent *theEvent, AppleEvent *reply, long refCon); extern OSErr DoPrintDocument(ImageHandle theImage, Boolean first); pascal OSErr HandleQuitApplication(AppleEvent *theEvent, AppleEvent *reply, long refCon); #endif \ No newline at end of file diff --git a/Headers/SCRN.h b/Headers/SCRN.h new file mode 100644 index 0000000..df4ac69 --- /dev/null +++ b/Headers/SCRN.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __SCRN__ #define __SCRN__ extern Boolean idSCRN(uchar *theData, long theSize, short refNum, FSSpec *theSpec); extern OSErr OpenSCRN(ImageHandle theImage); extern OSErr LoadSCRN(short theFile, ImageHandle theImage); extern OSErr DrawSCRN(Handle theHandle, JVDrawParamsHandle theParams); extern OSErr FixSCRN(ImageHandle theImage, Handle *finalData, Boolean palette); extern OSErr SaveSCRN(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle thePrivates); #endif \ No newline at end of file diff --git a/Headers/SaveOpen.h b/Headers/SaveOpen.h new file mode 100644 index 0000000..b6f15b3 --- /dev/null +++ b/Headers/SaveOpen.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __SAVEOPEN__ #define __SAVEOPEN__ enum { kCropNothing = 0, kCropIcon = 1, kCropImage = 2 }; OSErr DoSaveDocument(ImageHandle theImage, FSSpec *theSpec, OSType theType, Boolean preview, Boolean palette, Boolean icons, short cropWhat); OSErr DoOpenDocument(FSSpec *theFile, Boolean first, DescType openScreen, DescType openFull, Boolean autoExpand, Boolean openVisible, DescType openPalette, DescType drawQuality, Boolean openBitmaps, Boolean autoComments, Boolean fixTypes, Boolean fixCreator); OSErr ReadFile(ImageHandle theImage, Boolean fixTypes, Boolean fixCreator); short IDImage(short theFile, FSSpec *theSpec); OSErr InitImage(ImageHandle theImage, DescType openScreen, DescType openFull, DescType drawQuality, Boolean visible); extern OSErr DefaultLoad(short theFile, ImageHandle theImage); extern OSErr DefaultSave(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, OSType theType); Boolean UseFullScreen(ImageHandle theImage, DescType openFull, Boolean visible); OSErr PickFirstPalette(ImageHandle theImage, DescType openPalette); OSErr RenderOffscreen(ImageHandle theImage, Boolean openBitmaps); #endif \ No newline at end of file diff --git a/Headers/SendAppleEvents.h b/Headers/SendAppleEvents.h new file mode 100644 index 0000000..dd0684c --- /dev/null +++ b/Headers/SendAppleEvents.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __SENDAPPLEEVENTS__ #define __SENDAPPLEEVENTS__ extern OSErr SendSetWindowBounds(WindowPtr theWindow, Rect *theRect); extern OSErr SendSetZoomed(WindowPtr theWindow, Boolean zoomed); extern OSErr SendNewPalette(ImageHandle theImage, DescType thePalette); extern OSErr SendDither(ImageHandle theImage, Boolean dither); extern OSErr SendQuality(ImageHandle theImage, DescType theQuality); extern OSErr SendSetSelection(ImageHandle theImage, Rect *theRect); extern OSErr SendCloneDocument(ImageHandle theImage, ImageHandle *theNewImage); extern OSErr SendSetImageBounds(WindowPtr theWindow, Rect *theRect); extern OSErr SendSetWindowVis(WindowPtr theWindow, Boolean visible); extern OSErr SendOpenDocument(FSSpec *theSpec); extern OSErr SendCreateWindow(DescType windowID); extern OSErr SendCloseWindow(WindowPtr theWindow); extern OSErr SendSaveDocument(FSSpec *theSpec, OSType theFormat, Boolean preview, Boolean palette, Boolean icons, short cropWhat); extern OSErr SendSlideShow(void); extern OSErr SendPrintDocument(ImageHandle theImage); extern OSErr SendQuitApplication(void); extern OSErr SendSetFullScreen(WindowPtr theWindow, Boolean full); extern OSErr SendSetDrawBounds(WindowPtr theWindow, Rect *theRect); extern OSErr SendMoveToFront(WindowPtr theWindow); extern OSErr SendCopy(void); #endif \ No newline at end of file diff --git a/Headers/SlideControlsWindow.h b/Headers/SlideControlsWindow.h new file mode 100644 index 0000000..d1806a6 --- /dev/null +++ b/Headers/SlideControlsWindow.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __SLIDECONTROLSWINDOW__ #define __SLIDECONTROLSWINDOW__ enum { standard = 0, depressed = 1, disabled = 2 }; enum { kReverseButton = 0, kStopButton = 1, kPauseButton = 2, kForwardButton = 3, kHideButton = 4 }; extern OSErr OpenSlideControls(void); extern void CloseSlideControls(void); extern WindowPtr GetSlideControlsWindow(void); extern void SetSlideControlButton(short id, short status); extern short GetSlideControlButton(short id); extern void DrawSlideControlsWindow(void); extern void HandleSlideControlsClick(Point where, short modifiers, Boolean actNow); extern void HandleSlideControlsKey(char theChar, short modifiers, Boolean actNow); extern Boolean HandleUserControlButton(short button); extern Boolean HandleAutomaticButton(short button); extern Boolean PauseSlideShow(Boolean *advance); extern Boolean HideSlideShow(Boolean *advance); extern void SetSlideControlsText(StringPtr string0, StringPtr string1, StringPtr string2, StringPtr string3); extern void DoSlideControlsHelp(Point globalPt); #endif \ No newline at end of file diff --git a/Headers/SlideShow.h b/Headers/SlideShow.h new file mode 100644 index 0000000..d6fa279 --- /dev/null +++ b/Headers/SlideShow.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __SLIDESHOW__ #define __SLIDESHOW__ /* * sSlideItem = linked list item containing information pertaining to the current * slide image [SlideItem, *SlidePtr, **SlideHandle] */ typedef struct SlideItem { struct SlideItem **next; // pointer to next slide item Boolean mem; // flag: true if the given image is in memory FSSpec spec; // the filespec for the image } SlideItem, *SlidePtr, **SlideHandle; typedef struct LoopCheck { struct LoopCheck *prev; short vRefNum; long dirID; } LoopCheck, *LoopCheckPtr; #if defined(powerc) || defined(__powerc) #pragma options align=mac68k #endif typedef struct SlideOptions { Boolean userControl; // user-controlled? long delay; // delay time, in seconds Boolean random; // show slide in random order? Boolean repeat; // repeat indefinitely? Boolean noErrors; // stop when we get an error? Boolean hideWindoids; // hide the windoids? Boolean hideControls; // hide the controls? Boolean autoComments; // automatically show comments? Boolean fromMemory; // run from memory or disk? Boolean recursive; // do a recursive directory scan? Boolean allFiles; // try to import files? Boolean fileNames; // display filenames? Boolean offscreen; // render offscreen first? } SlideOptions, *SlideOptionsPtr, **SlideOptionsHandle; #if defined(powerc) || defined(__powerc) #pragma options align=reset #endif enum { kStopped = 0, kRunning = 1, kPaused = 2 }; extern WindowPtr GetSlideBackWindow(void); extern void CloseSlideBackWindow(void); extern void DrawSlideBackWindow(void); extern void ResetSlideTimer(void); extern void HandleSlideNullEvent(void); extern void PointToPreviousSlide(void); extern void InitSlideShow(void); extern void ReinitSlideShow(SlideOptionsPtr oldOptions); extern OSErr AddSlideDir(FSSpec *spec, Boolean recursive, ICMProgressProcRecordPtr theProg, LoopCheckPtr theLoop); extern void CleanUpSlideShow(void); extern Boolean LoadSlide(Boolean *advance); extern Boolean EndSlideShow(void); extern Boolean NextSlide(Boolean *advance); #endif \ No newline at end of file diff --git a/Headers/SlideShowOptions.h b/Headers/SlideShowOptions.h new file mode 100644 index 0000000..c7a9d3c --- /dev/null +++ b/Headers/SlideShowOptions.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __SLIDESHOWOPTIONS__ #define __SLIDESHOWOPTIONS__ OSErr OpenSlideOptions(void); void CloseSlideOptions(void); WindowPtr GetSlideOptionsWindow(void); void HandleSlideOptionsEvent(short theItem); Boolean HandleSlideOptionsKey(char theChar); void UpdateSlideOptionsButtons(void); pascal void SlideOptionsUser(DialogPtr theDialog, short theItem); extern OSErr GetSlideSpec(FSSpec *theSpec); #endif \ No newline at end of file diff --git a/Headers/StandardFolder.h b/Headers/StandardFolder.h new file mode 100644 index 0000000..de76fb3 --- /dev/null +++ b/Headers/StandardFolder.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __STANDARDFOLDER__ #define __STANDARDFOLDER__ /* * sFolder = Standard get folder structure [SFData, SFDataPtr] */ typedef struct SFData { StandardFileReply *replyPtr; FSSpec oldSelection, origSelection; } SFData, *SFDataPtr; Boolean StandardGetFolder(FSSpec *theSpec); pascal Boolean StdFolderFilter(CInfoPBPtr pb, long refCon); pascal short StdFolderHook(short item, DialogPtr theDialog, Ptr userData); void SetSelectButtonName(StringPtr selName, Boolean hilited, DialogPtr theDialog); OSErr MakeCanonFSSpec(FSSpec *theSpec); OSErr GetDeskFolderSpec(FSSpec *theSpec, short vRefNum); Boolean ShouldHiliteSelect(FSSpec *theSpec); extern Boolean SameFile(FSSpec *file1, FSSpec *file2); #endif \ No newline at end of file diff --git a/Headers/StatisticsWindow.h b/Headers/StatisticsWindow.h new file mode 100644 index 0000000..528d22e --- /dev/null +++ b/Headers/StatisticsWindow.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __STATISTICSWINDOW__ #define __STATISTICSWINDOW__ OSErr OpenStats(void); void CloseStats(void); void SizeStats(Boolean zoomed); void ZoomStats(void); WindowPtr GetStatWindow(void); extern void HandleStatClick(EventRecord *theEvent); void SetStatistics(void); void DrawStatWindow(void); void DrawStatSummary(ImageHandle theImage, short *vPos); void DrawStatFileName(ImageHandle theImage, short *vPos); void DrawStatImageSize(ImageHandle theImage, short *vPos); void DrawStatImageStatus(ImageHandle theImage, short *vPos); void DrawStatImageColors(ImageHandle theImage, short *vPos); void DrawStatCompression(ImageHandle theImage, short *vPos); void DrawStatFileFormat(ImageHandle theImage, short *vPos); void DrawStatImageLength(ImageHandle theImage, short *vPos); void DrawStatDisplayedSize(ImageHandle theImage, short *vPos); void DrawStatDisplayedColors(ImageHandle theImage, short *vPos); void DrawStatDisplayQuality(ImageHandle theImage, short *vPos); void DrawStatDisplayTime(ImageHandle theImage, short *vPos); void DrawStatOffscreen(ImageHandle theImage, short *vPos); void DrawStatFree(ImageHandle theImage, short *vPos); void DrawStatItem(short vPos, short item, StringPtr theNum); extern void IdleCredits(void); void DoStatsHelp(Point globalPt); #endif \ No newline at end of file diff --git a/Headers/TIFF.h b/Headers/TIFF.h new file mode 100644 index 0000000..c48db48 --- /dev/null +++ b/Headers/TIFF.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __TIFF__ #define __TIFF__ extern Boolean idTIFF(uchar *theData, long theSize, short refNum, FSSpec *theSpec); extern OSErr OpenTIFF(ImageHandle theImage); extern OSErr DrawTIFF(Handle theHandle, JVDrawParamsHandle theParams); extern OSErr CloneTIFF(ImageHandle origImage, ImageHandle newImage); extern OSErr CloseTIFF(ImageHandle theImage); #endif \ No newline at end of file diff --git a/Headers/ViewMenu.h b/Headers/ViewMenu.h new file mode 100644 index 0000000..5541ef8 --- /dev/null +++ b/Headers/ViewMenu.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __VIEWMENU__ #define __VIEWMENU__ void HandleViewChoice(short theItem); void ForceScreenSize(ImageHandle theImage, Rect *srcRect); #endif \ No newline at end of file diff --git a/Headers/WindowMenu.h b/Headers/WindowMenu.h new file mode 100644 index 0000000..2cebead --- /dev/null +++ b/Headers/WindowMenu.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __WINDOWMENU__ #define __WINDOWMENU__ void HandleWindowChoice(short theItem); #endif \ No newline at end of file diff --git a/Headers/WindowUtils.h b/Headers/WindowUtils.h new file mode 100644 index 0000000..6b4e6e9 --- /dev/null +++ b/Headers/WindowUtils.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __WINDOWUTILS__ #define __WINDOWUTILS__ void SaveWindowPosition(DialogPtr theDialog, Rect *position); void PlaceWindow(WindowPtr theWindow, Rect *theRect, Point defaultLoc); void ChangeActive(WindowPtr theWindow); OSErr DoCloneWindow(WindowPtr theWindow, WindowPtr behindWindow, WindowPtr *newWindow); OSErr DoCloseWindow(WindowPtr theWindow, Boolean restore); OSErr DoCreateWindow(DescType theType, WindowPtr behindWindow, WindowPtr *theWindow); OSErr DoMoveWindow(WindowPtr theWindow, WindowPtr behindWindow); Boolean IsZoomed(WindowPtr theWindow); OSErr DoZoomWindow(WindowPtr theWindow, Boolean zoomed); OSErr MakeNewWindow(ImageHandle theImage, Boolean first, Boolean autoExpand); void ScaleRect(Rect *theRect, MonitorHandle theMonitor, Boolean full, Boolean autoExpand); void MakeTitle(ImageHandle theImage, StringPtr theTitle); void PositionWindow(Rect *theRect, MonitorHandle theMonitor); Boolean SlotTaken(Rect *theRect); Boolean ResizeWindow(ImageHandle theImage); Boolean NudgeWindowRect(Rect *windowRect, MonitorHandle theMonitor); #endif \ No newline at end of file diff --git a/Headers/cApplication.h b/Headers/cApplication.h new file mode 100644 index 0000000..c5ea13d --- /dev/null +++ b/Headers/cApplication.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CAPPLICATION__ #define __CAPPLICATION__ pascal OSErr AppPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetApplicationData(DescType typeWanted, AEDesc *theData); OSErr GetAppPropertyData(DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetAppPropertyData(DescType theProperty, AEDesc *theData); OSErr MakeAppPropertyObject(DescType theProperty, AEDesc *theObject); #endif \ No newline at end of file diff --git a/Headers/cDocument.h b/Headers/cDocument.h new file mode 100644 index 0000000..ecf28e9 --- /dev/null +++ b/Headers/cDocument.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CDOCUMENT__ #define __CDOCUMENT__ pascal OSErr DocumentAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); pascal OSErr DocPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetDocumentData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData); OSErr GetDocPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetDocPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData); OSErr MakeDocumentObject(WindowPtr theWindow, AEDesc *theObject); OSErr MakeDocPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject); Boolean IsValidForOne(DescType keyForm, AEDesc *keyData); void PurgeNonDocuments(ObjectTokenHandle theList); OSErr GetNamedDocument(AEDesc *keyData, ObjectTokenHandle *theList); short CountDocuments(void); WindowPtr IndexedDocument(short index); short GetDocumentIndex(WindowPtr theWindow); #endif \ No newline at end of file diff --git a/Headers/cDrawingArea.h b/Headers/cDrawingArea.h new file mode 100644 index 0000000..a5eef5a --- /dev/null +++ b/Headers/cDrawingArea.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CDRAWINGAREA__ #define __CDRAWINGAREA__ pascal OSErr DrawingAreaAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); pascal OSErr DrawPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetDrawingAreaData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData); OSErr GetDrawPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetDrawPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData); OSErr MakeDrawingAreaObject(WindowPtr theWindow, AEDesc *theObject); OSErr MakeDrawPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject); OSErr DoSetColorTable(WindowPtr theWindow, CTabHandle theColors); OSErr DoSetPalette(WindowPtr theWindow, DescType thePalette); OSErr DoSetImageDither(ImageHandle theImage, Boolean dither); OSErr DoSetImageQuality(ImageHandle theImage, DescType theQuality); extern OSErr DoSetDrawBounds(ImageHandle theImage, Rect *theRect); #endif \ No newline at end of file diff --git a/Headers/cFile.h b/Headers/cFile.h new file mode 100644 index 0000000..414de35 --- /dev/null +++ b/Headers/cFile.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CFILE__ #define __CFILE__ pascal OSErr FileAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); pascal OSErr FilePropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetFileData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData); OSErr GetFilePropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetFilePropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData); OSErr MakeFileObject(WindowPtr theWindow, AEDesc *theObject); OSErr MakeFilePropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject); #endif \ No newline at end of file diff --git a/Headers/cImage.h b/Headers/cImage.h new file mode 100644 index 0000000..8c3a383 --- /dev/null +++ b/Headers/cImage.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CIMAGE__ #define __CIMAGE__ pascal OSErr ImageAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); pascal OSErr ImagePropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetImageData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData); OSErr GetImagePropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetImagePropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData); OSErr MakeImageObject(WindowPtr theWindow, AEDesc *theObject); OSErr MakeImagePropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject); OSErr DoSetImageBounds(ImageHandle theImage, Rect *theRect); #endif \ No newline at end of file diff --git a/Headers/cPixelMap.h b/Headers/cPixelMap.h new file mode 100644 index 0000000..45c2d14 --- /dev/null +++ b/Headers/cPixelMap.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CPIXELMAP__ #define __CPIXELMAP__ pascal OSErr PixelMapAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); pascal OSErr PixelPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetPixelMapData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData); OSErr GetPixelPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetPixelPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData); OSErr MakePixelMapObject(WindowPtr theWindow, AEDesc *theObject); OSErr MakePixelPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject); #endif \ No newline at end of file diff --git a/Headers/cSelection.h b/Headers/cSelection.h new file mode 100644 index 0000000..07594d8 --- /dev/null +++ b/Headers/cSelection.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CSELECTION__ #define __CSELECTION__ pascal OSErr SelectionAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); pascal OSErr SelPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetSelectionData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData); OSErr GetSelPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetSelPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData); OSErr MakeSelectionObject(WindowPtr theWindow, AEDesc *theObject); OSErr MakeSelPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject); extern OSErr DoSetSelection(ImageHandle theImage, Rect *theRect); #endif \ No newline at end of file diff --git a/Headers/cWindow.h b/Headers/cWindow.h new file mode 100644 index 0000000..3e96ad4 --- /dev/null +++ b/Headers/cWindow.h @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #ifndef __CWINDOW__ #define __CWINDOW__ pascal OSErr WindowAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); pascal OSErr WinPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon); OSErr GetWindowData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData); OSErr GetWinPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData); OSErr SetWinPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData); OSErr GetAbsoluteWindow(AEDesc *keyData, ObjectTokenHandle *theList); OSErr GetNamedWindow(AEDesc *keyData, ObjectTokenHandle *theList); short CountWindows(void); WindowPtr IndexedWindow(short index); short GetWindowIndex(WindowPtr theWindow); OSErr MakeWinPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject); OSErr MakeWindowObject(WindowPtr theWindow, AEDesc *theObject); ObjectTokenHandle MakeAllWindowsToken(void); ObjectTokenHandle MakeSingleObjectToken(Ptr theObject); OSErr DoSetWindowBounds(WindowPtr theWindow, Rect *bounds); OSErr DoSetWindowFull(WindowPtr theWindow, Boolean full); OSErr DoSetWindowTitle(WindowPtr theWindow, StringPtr theString); extern OSErr DoSetWindowVisible(WindowPtr theWindow, Boolean visible); #endif \ No newline at end of file diff --git a/Headers/jconfig.h b/Headers/jconfig.h new file mode 100644 index 0000000..e6f6b63 --- /dev/null +++ b/Headers/jconfig.h @@ -0,0 +1 @@ +/* * jconfig.doc * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file documents the configuration options that are required to * customize the JPEG software for a particular system. * * The actual configuration options for a particular installation are stored * in jconfig.h. On many machines, jconfig.h can be generated automatically * or copied from one of the "canned" jconfig files that we supply. But if * you need to generate a jconfig.h file by hand, this file tells you how. * * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. * EDIT A COPY NAMED JCONFIG.H. */ /* * These symbols indicate the properties of your machine or compiler. * #define the symbol if yes, #undef it if no. */ /* Does your compiler support function prototypes? * (If not, you also need to use ansi2knr, see install.doc) */ #define HAVE_PROTOTYPES /* Does your compiler support the declaration "unsigned char" ? * How about "unsigned short" ? */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define "const" as empty if your compiler doesn't know the "const" keyword. */ /* #define const */ /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. */ #undef CHAR_IS_UNSIGNED /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDDEF_H /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDLIB_H /* Define this if your system does not have an ANSI/SysV , * but does have a BSD-style . */ #undef NEED_BSD_STRINGS /* Define this if your system does not provide typedef size_t in any of the * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in * instead. */ #undef NEED_SYS_TYPES_H /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #undef NEED_FAR_POINTERS /* Define this if your linker needs global names to be unique in less * than the first 15 characters. */ #undef NEED_SHORT_EXTERNAL_NAMES /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you * actually get "missing structure definition" warnings or errors while * compiling the JPEG code. */ #undef INCOMPLETE_TYPES_BROKEN /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS has been defined. */ #ifdef JPEG_INTERNALS /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ /* * The remaining options do not affect the JPEG library proper, * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). * Other applications can ignore these. */ #ifdef JPEG_CJPEG_DJPEG /* These defines indicate which image (non-JPEG) file formats are allowed. */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of cjpeg.c or djpeg.c. */ #undef TWO_FILE_COMMANDLINE /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #undef NEED_SIGNAL_CATCHER /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Headers/jerror.h b/Headers/jerror.h new file mode 100644 index 0000000..3ea6cda --- /dev/null +++ b/Headers/jerror.h @@ -0,0 +1 @@ +/* * jerror.h * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the error and message codes for the JPEG library. * Edit this file to add new codes, or to translate the message strings to * some other language. * A set of error-reporting macros are defined too. Some applications using * the JPEG library may wish to include this file to get the error codes * and/or the macros. */ /* To define the enum list of message codes, include this file without * defining JMAKE_MSG_TABLE. To create the message string table, include it * again with JMAKE_MSG_TABLE defined (this should be done in just one module). */ #ifdef JMAKE_MSG_TABLE const char * const jpeg_message_table[] = { #define JMESSAGE(code,string) string , #else /* not JMAKE_MSG_TABLE */ typedef enum { #define JMESSAGE(code,string) code , #endif /* JMAKE_MSG_TABLE */ JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK should be less than 64K") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") JMESSAGE(JERR_DHT_COUNTS, "Bogus DHT counts") JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") JMESSAGE(JERR_EMS_READ, "Read from EMS failed") JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") JMESSAGE(JERR_FILE_READ, "Input file read error") JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") JMESSAGE(JERR_JFIF_MAJOR, "Unsupported JFIF revision number %d.%02d") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") JMESSAGE(JERR_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") JMESSAGE(JERR_PIPE_BUG, "Pipeline controller messed up") JMESSAGE(JERR_QUANT_COMPONENTS, "Cannot quantize more than %d color components") JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported SOF marker type 0x%02x") JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") JMESSAGE(JERR_TFILE_WRITE, "Write failed on temporary file --- out of disk space?") JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") JMESSAGE(JERR_XMS_READ, "Read from XMS failed") JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) JMESSAGE(JMSG_VERSION, JVERSION) JMESSAGE(JTRC_16BIT_TABLES, "Caution: quantization tables are too coarse for baseline JPEG") JMESSAGE(JTRC_ADOBE, "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") JMESSAGE(JTRC_DRI, "Define Restart Interval %u") JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") JMESSAGE(JTRC_EOI, "End Of Image") JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") JMESSAGE(JTRC_JFIF, "JFIF APP0 marker, density %dx%d %d") JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, "Warning: thumbnail image size does not match data length %u") JMESSAGE(JTRC_JFIF_MINOR, "Warning: unknown JFIF revision number %d.%02d") JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") JMESSAGE(JTRC_MISC_MARKER, "Skipping marker 0x%02x, length %u") JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") JMESSAGE(JTRC_RST, "RST%d") JMESSAGE(JTRC_SMOOTH_NOTIMPL, "Smoothing not supported with nonstandard sampling ratios") JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") JMESSAGE(JTRC_SOI, "Start of Image") JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") JMESSAGE(JTRC_UNKNOWN_IDS, "Unrecognized component IDs %d %d %d, assuming YCbCr") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") JMESSAGE(JWRN_MUST_RESYNC, "Corrupt JPEG data: found marker 0x%02x instead of RST%d") #ifdef JMAKE_MSG_TABLE NULL }; #else /* not JMAKE_MSG_TABLE */ JMSG_LASTMSGCODE } J_MESSAGE_CODE; #endif /* JMAKE_MSG_TABLE */ #undef JMESSAGE #ifndef JMAKE_MSG_TABLE /* Macros to simplify using the error and trace message stuff */ /* The first parameter is either type of cinfo pointer */ /* Fatal errors (print message and exit) */ #define ERREXIT(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT3(cinfo,code,p1,p2,p3) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (cinfo)->err->msg_parm.i[3] = (p4), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXITS(cinfo,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define MAKESTMT(stuff) do { stuff } while (0) /* Nonfatal errors (we can keep going, but the data is probably corrupt) */ #define WARNMS(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) /* Informational/debugging messages */ #define TRACEMS(cinfo,lvl,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS1(cinfo,lvl,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS2(cinfo,lvl,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMSS(cinfo,lvl,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #endif /* JMAKE_MSG_TABLE */ \ No newline at end of file diff --git a/Headers/jmorecfg.h b/Headers/jmorecfg.h new file mode 100644 index 0000000..fae88c2 --- /dev/null +++ b/Headers/jmorecfg.h @@ -0,0 +1 @@ +/* * jmorecfg.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains additional configuration options that customize the * JPEG software for special applications or support machine-dependent * optimizations. Most users will not need to touch this file. */ /* * Define BITS_IN_JSAMPLE as either * 8 for 8-bit sample values (the usual setting) * 12 for 12-bit sample values * Only 8 and 12 are legal data precisions for lossy JPEG according to the * JPEG standard, and the IJG code does not support anything else! * We do not support run-time selection of data precision, sorry. */ #define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ /* * Maximum number of components (color channels) allowed in JPEG image. * To meet the letter of the JPEG spec, set this to 255. However, darn * few applications need more than 4 channels (maybe 5 for CMYK + alpha * mask). We recommend 10 as a reasonable compromise; use 4 if you are * really short on memory. (Each allowed component costs a hundred or so * bytes of storage, whether actually used in an image or not.) */ #define MAX_COMPONENTS 10 /* maximum number of image components */ /* * Basic data types. * You may need to change these if you have a machine with unusual data * type sizes; for example, "char" not 8 bits, "short" not 16 bits, * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, * but it had better be at least 16. */ /* Representation of a single sample (pixel element value). * We frequently allocate large arrays of these, so it's important to keep * them small. But if you have memory to burn and access to char or short * arrays is very slow on your hardware, you might want to change these. */ #if BITS_IN_JSAMPLE == 8 /* JSAMPLE should be the smallest type that will hold the values 0..255. * You can use a signed char by having GETJSAMPLE mask it with 0xFF. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JSAMPLE; #ifdef CHAR_IS_UNSIGNED #define GETJSAMPLE(value) (value) #else #define GETJSAMPLE(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ #define MAXJSAMPLE 255 #define CENTERJSAMPLE 128 #endif /* BITS_IN_JSAMPLE == 8 */ #if BITS_IN_JSAMPLE == 12 /* JSAMPLE should be the smallest type that will hold the values 0..4095. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) (value) #define MAXJSAMPLE 4095 #define CENTERJSAMPLE 2048 #endif /* BITS_IN_JSAMPLE == 12 */ /* Representation of a DCT frequency coefficient. * This should be a signed value of at least 16 bits; "short" is usually OK. * Again, we allocate large arrays of these, but you can change to int * if you have memory to burn and "short" is really slow. */ typedef short JCOEF; /* Compressed datastreams are represented as arrays of JOCTET. * These must be EXACTLY 8 bits wide, at least once they are written to * external storage. Note that when using the stdio data source/destination * managers, this is also the data type passed to fread/fwrite. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JOCTET; #define GETJOCTET(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JOCTET; #ifdef CHAR_IS_UNSIGNED #define GETJOCTET(value) (value) #else #define GETJOCTET(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* These typedefs are used for various table entries and so forth. * They must be at least as wide as specified; but making them too big * won't cost a huge amount of memory, so we don't provide special * extraction code like we did for JSAMPLE. (In other words, these * typedefs live at a different point on the speed/space tradeoff curve.) */ /* UINT8 must hold at least the values 0..255. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; #else /* not HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char UINT8; #else /* not CHAR_IS_UNSIGNED */ typedef short UINT8; #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* UINT16 must hold at least the values 0..65535. */ #ifdef HAVE_UNSIGNED_SHORT typedef unsigned short UINT16; #else /* not HAVE_UNSIGNED_SHORT */ typedef unsigned int UINT16; #endif /* HAVE_UNSIGNED_SHORT */ /* INT16 must hold at least the values -32768..32767. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ typedef short INT16; #endif /* INT32 must hold at least signed 32-bit values. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ typedef long INT32; #endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore * "unsigned int" is sufficient on all machines. However, if you need to * handle larger images and you don't mind deviating from the spec, you * can change this datatype. */ typedef unsigned int JDIMENSION; #define JPEG_MAX_DIMENSION 65500 /* a tad under 64K to prevent overflows */ /* These defines are used in all function definitions and extern declarations. * You could modify them if you need to change function linkage conventions. * Another application is to make all functions global for use with debuggers * or code profilers that require it. */ #define METHODDEF static /* a function called through method pointers */ #define LOCAL static /* a function used only in its module */ #define GLOBAL /* a function referenced thru EXTERNs */ #define EXTERN extern /* a reference to a GLOBAL function */ /* Here is the pseudo-keyword for declaring pointers that must be "far" * on 80x86 machines. Most of the specialized coding for 80x86 is handled * by just saying "FAR *" where such a pointer is needed. In a few places * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif /* * On a few systems, type boolean and/or its values FALSE, TRUE may appear * in standard header files. Or you may have conflicts with application- * specific header files that you want to include together with these files. * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. */ #ifndef HAVE_BOOLEAN typedef int boolean; #endif #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. */ #ifdef JPEG_INTERNALS #define JPEG_INTERNAL_OPTIONS #endif #ifdef JPEG_INTERNAL_OPTIONS /* * These defines indicate whether to include various optional functions. * Undefining some of these symbols will produce a smaller but less capable * library. Note that you can leave certain source files out of the * compilation/linking process if you've #undef'd the corresponding symbols. * (You may HAVE to do that if your compiler doesn't like null source files.) */ /* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ /* Encoder capability options: */ #undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #undef C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? (NYI) */ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit * precision, so jchuff.c normally uses entropy optimization to compute * usable tables for higher precision. If you don't want to do optimization, * you'll have to supply different default Huffman tables. */ #undef INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ /* Decoder capability options: */ #undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #undef D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #undef BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */ #undef QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ // CHANGED! #undef'ed #undef QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ // CHANGED! #undef'ed /* more capability options later, no doubt */ /* If your compiler supports inline functions, define INLINE * as the inline keyword; otherwise define it as empty. */ #ifndef INLINE #ifdef __GNUC__ /* for instance, GNU C knows about inline */ #define INLINE __inline__ #endif #ifndef INLINE #define INLINE /* default is to define it as empty */ #endif #endif /* Typedef for multiplying quantized coefficients by pre-IDCT multipliers. * Must be a signed type. Use short if short*short is faster than int*int. */ #if BITS_IN_JSAMPLE == 8 typedef int MULTIPLIER; /* may want short on some machines */ #else typedef INT32 MULTIPLIER; /* need more than 16 bits in this case */ #endif #endif /* JPEG_INTERNAL_OPTIONS */ \ No newline at end of file diff --git a/Headers/jpeglib.h b/Headers/jpeglib.h new file mode 100644 index 0000000..ea7eb48 --- /dev/null +++ b/Headers/jpeglib.h @@ -0,0 +1 @@ +/* * jpeglib.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the application interface for the JPEG library. * Most applications using the library need only include this file, * and perhaps jerror.h if they want to know the exact error codes. */ /* * First we include the configuration files that record how this * installation of the JPEG library is set up. jconfig.h can be * generated automatically for many systems. jmorecfg.h contains * manual configuration options that most people need not worry about. */ #ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ #include "jconfig.h" /* widely used configuration options */ #endif #include "jmorecfg.h" /* seldom changed options */ /* Various constants determining the sizes of things. * All of these are specified by the JPEG standard, so don't change them * if you want to be compatible. */ #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ #define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ #define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ #define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ #define MAX_BLOCKS_IN_MCU 10 /* JPEG limit on # of blocks in an MCU */ /* This macro is used to declare a "method", that is, a function pointer. * We want to supply prototype parameters if the compiler can cope. * Note that the arglist parameter must be parenthesized! */ #ifdef HAVE_PROTOTYPES #define JMETHOD(type,methodname,arglist) type (*methodname) arglist #else #define JMETHOD(type,methodname,arglist) type (*methodname) () #endif /* Data structures for images (arrays of samples and of DCT coefficients). * On 80x86 machines, the image arrays are too big for near pointers, * but the pointer arrays can fit in near memory. */ typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ /* Types for JPEG compression parameters and working tables. */ /* DCT coefficient quantization tables. */ typedef struct { /* This field directly represents the contents of a JPEG DQT marker. * Note: the values are always given in zigzag order. */ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ /* NB: there are additional private fields in an actual quantization data * structure, so don't allocate one directly. Use jpeg_alloc_quant_table. */ } JQUANT_TBL; /* Huffman coding tables. */ typedef struct { /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ /* length k bits; bits[0] is unused */ UINT8 huffval[256]; /* The symbols, in order of incr code length */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ /* NB: there are additional private fields in an actual Huffman-table data * structure, so don't allocate one directly. Use jpeg_alloc_huff_table. */ } JHUFF_TBL; /* Basic info about one component (color channel). */ typedef struct { /* These values are fixed over the whole image. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOF marker. */ int component_id; /* identifier for this component (0..255) */ int component_index; /* its index in SOF or cinfo->comp_info[] */ int h_samp_factor; /* horizontal sampling factor (1..4) */ int v_samp_factor; /* vertical sampling factor (1..4) */ int quant_tbl_no; /* quantization table selector (0..3) */ /* These values may vary between scans. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOS marker. */ int dc_tbl_no; /* DC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */ /* Remaining fields should be treated as private by applications. */ /* These values are computed during compression or decompression startup: */ /* Component's size in DCT blocks. * Any dummy blocks added to complete an MCU are not counted; therefore * these values do not depend on whether a scan is interleaved or not. */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; /* Size of a DCT block in samples. Always DCTSIZE for compression. * For decompression this is the size of the output from one DCT block, * reflecting any scaling we choose to apply during the IDCT step. * Values of 1,2,4,8 are likely to be supported. Note that different * components may receive different IDCT scalings. */ int DCT_scaled_size; /* The downsampled dimensions are the component's actual, unpadded number * of samples at the main buffer (preprocessing/compression interface), thus * downsampled_width = ceil(image_width * Hi/Hmax) * and similarly for height. For decompression, IDCT scaling is included, so * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ /* This flag is used only for decompression. In cases where some of the * components will be ignored (eg grayscale output from YCbCr image), * we can skip most computations for the unused components. */ boolean component_needed; /* do we need the value of this component? */ /* These values are computed before starting a scan of the component: */ int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_height; /* number of blocks per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */ } jpeg_component_info; /* Known color spaces. */ typedef enum { JCS_UNKNOWN, /* error/unspecified */ JCS_GRAYSCALE, /* monochrome */ JCS_RGB, /* red/green/blue */ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ JCS_CMYK, /* C/M/Y/K */ JCS_YCCK /* Y/Cb/Cr/K */ } J_COLOR_SPACE; /* Common fields between JPEG compression and decompression master structs. */ #define jpeg_common_fields \ struct jpeg_error_mgr * err; /* Error handler module */\ struct jpeg_memory_mgr * mem; /* Memory manager module */\ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ boolean is_decompressor; /* so common code can tell which is which */\ int global_state /* for checking call sequence validity */ /* Routines that are to be used by both halves of the library are declared * to receive a pointer to this structure. There are no actual instances of * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. */ struct jpeg_common_struct { jpeg_common_fields; /* Fields common to both master struct types */ /* Additional fields follow in an actual jpeg_compress_struct or * jpeg_decompress_struct. All three structs must agree on these * initial fields! (This would be a lot cleaner in C++.) */ }; typedef struct jpeg_common_struct * j_common_ptr; typedef struct jpeg_compress_struct * j_compress_ptr; typedef struct jpeg_decompress_struct * j_decompress_ptr; /* Master record for a compression instance */ struct jpeg_compress_struct { jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ /* Destination for compressed data */ struct jpeg_destination_mgr * dest; /* Description of source image --- these fields must be filled in by * outer application before starting compression. in_color_space must * be correct before you can even call jpeg_set_defaults(). */ JDIMENSION image_width; /* input image width */ JDIMENSION image_height; /* input image height */ int input_components; /* # of color components in input image */ J_COLOR_SPACE in_color_space; /* colorspace of input image */ double input_gamma; /* image gamma of input image */ /* Compression parameters --- these fields must be set before calling * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to * initialize everything to reasonable defaults, then changing anything * the application specifically wants to change. That way you won't get * burnt when new parameters are added. Also note that there are several * helper routines to simplify changing parameters. */ int data_precision; /* bits of precision in image data */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean interleave; /* TRUE=interleaved output, FALSE=not */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */ /* The restart interval can be specified in absolute MCUs by setting * restart_interval, or in MCU rows by setting restart_in_rows * (in which case the correct restart_interval will be figured * for each scan). */ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ int restart_in_rows; /* if > 0, MCU rows per restart interval */ /* Parameters controlling emission of special markers. */ boolean write_JFIF_header; /* should a JFIF marker be written? */ /* These three values are not used by the JPEG code, merely copied */ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ /* ratio is defined by X_density/Y_density even when density_unit=0. */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean write_Adobe_marker; /* should an Adobe marker be written? */ /* State variable: index of next scanline to be written to * jpeg_write_scanlines(). Application may use this to control its * processing loop, e.g., "while (next_scanline < image_height)". */ JDIMENSION next_scanline; /* 0 .. image_height-1 */ /* Remaining fields are known throughout compressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during compression startup */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ /* * Links to compression subobjects (methods and private variables of modules) */ struct jpeg_comp_master * master; struct jpeg_c_main_controller * main; struct jpeg_c_prep_controller * prep; struct jpeg_c_coef_controller * coef; struct jpeg_marker_writer * marker; struct jpeg_color_converter * cconvert; struct jpeg_downsampler * downsample; struct jpeg_forward_dct * fdct; struct jpeg_entropy_encoder * entropy; }; /* Master record for a decompression instance */ struct jpeg_decompress_struct { jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ /* Source of compressed data */ struct jpeg_source_mgr * src; /* Basic description of image --- filled in by jpeg_read_header(). */ /* Application may inspect these values to decide how to process image. */ JDIMENSION image_width; /* nominal image width (from SOF marker) */ JDIMENSION image_height; /* nominal image height */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ /* Decompression processing parameters --- these fields must be set before * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes * them to default values. */ J_COLOR_SPACE out_color_space; /* colorspace for output */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */ double output_gamma; /* image gamma wanted in output */ boolean quantize_colors; /* T if output is a colormapped format */ /* the following are ignored if not quantize_colors: */ boolean two_pass_quantize; /* use two-pass color quantization? */ boolean use_dithering; /* want color dithering? */ int desired_number_of_colors; /* max number of colors to use */ boolean do_block_smoothing; /* T = apply cross-block smoothing */ boolean do_fancy_upsampling; /* T = apply fancy upsampling */ /* Description of actual output image that will be returned to application. * These fields are computed by jpeg_start_decompress(). * You can also use jpeg_calc_output_dimensions() to determine these values * in advance of calling jpeg_start_decompress(). */ JDIMENSION output_width; /* scaled image width */ JDIMENSION output_height; /* scaled image height */ int out_color_components; /* # of color components in out_color_space */ int output_components; /* # of color components returned */ /* output_components is 1 (a colormap index) when quantizing colors; * otherwise it equals out_color_components. */ int rec_outbuf_height; /* min recommended height of scanline buffer */ /* If the buffer passed to jpeg_read_scanlines() is less than this many rows * high, space and time will be wasted due to unnecessary data copying. * Usually rec_outbuf_height will be 1 or 2, at most 4. */ /* When quantizing colors, the output colormap is described by these fields. * The application can supply a colormap by setting colormap non-NULL before * calling jpeg_start_decompress; otherwise a colormap is created during * jpeg_start_decompress. * The map has out_color_components rows and actual_number_of_colors columns. */ int actual_number_of_colors; /* number of entries in use */ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ /* State variable: index of next scaled scanline to be read from * jpeg_read_scanlines(). Application may use this to control its * processing loop, e.g., "while (output_scanline < output_height)". */ JDIMENSION output_scanline; /* 0 .. output_height-1 */ /* Internal JPEG parameters --- the application usually need not look at * these fields. */ /* Quantization and Huffman tables are carried forward across input * datastreams when processing abbreviated JPEG datastreams. */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ /* These parameters are never carried across datastreams, since they * are given in SOF/SOS markers or defined to be reset by SOI. */ int data_precision; /* bits of precision in image data */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ /* These fields record data obtained from optional markers recognized by * the JPEG library. */ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ /* Data copied from JFIF marker: */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ UINT8 Adobe_transform; /* Color transform code from Adobe marker */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ /* Remaining fields are known throughout decompressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during decompression startup */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be output by coef ctlr */ /* The coefficient controller outputs data in units of MCU rows as defined * for fully interleaved scans (whether the JPEG file is interleaved or not). * There are v_samp_factor * DCT_scaled_size sample rows of each component * in an "iMCU" (interleaved MCU) row. */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ /* This field is shared between entropy decoder and marker parser. * It is either zero or the code of a JPEG marker that has been * read from the data source, but has not yet been processed. */ int unread_marker; /* * Links to decompression subobjects (methods, private variables of modules) */ struct jpeg_decomp_master * master; struct jpeg_d_main_controller * main; struct jpeg_d_coef_controller * coef; struct jpeg_d_post_controller * post; struct jpeg_marker_reader * marker; struct jpeg_entropy_decoder * entropy; struct jpeg_inverse_dct * idct; struct jpeg_upsampler * upsample; struct jpeg_color_deconverter * cconvert; struct jpeg_color_quantizer * cquantize; }; /* "Object" declarations for JPEG modules that may be supplied or called * directly by the surrounding application. * As with all objects in the JPEG library, these structs only define the * publicly visible methods and state variables of a module. Additional * private fields may exist after the public ones. */ /* Error handler object */ struct jpeg_error_mgr { /* Error exit handler: does not return to caller */ JMETHOD(void, error_exit, (j_common_ptr cinfo)); /* Conditionally emit a trace or warning message */ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); /* Routine that actually outputs a trace or error message */ JMETHOD(void, output_message, (j_common_ptr cinfo)); /* Format a message string for the most recent JPEG error or message */ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ /* Reset error state variables at start of a new image */ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); /* The message ID code and any parameters are saved here. * A message can have one string parameter or up to 8 int parameters. */ int msg_code; #define JMSG_STR_PARM_MAX 80 union { int i[8]; char s[JMSG_STR_PARM_MAX]; } msg_parm; /* Standard state variables for error facility */ int trace_level; /* max msg_level that will be displayed */ /* For recoverable corrupt-data errors, we emit a warning message, * but keep going unless emit_message chooses to abort. emit_message * should count warnings in num_warnings. The surrounding application * can check for bad data by seeing if num_warnings is nonzero at the * end of processing. */ long num_warnings; /* number of corrupt-data warnings */ /* These fields point to the table(s) of error message strings. * An application can change the table pointer to switch to a different * message list (typically, to change the language in which errors are * reported). Some applications may wish to add additional error codes * that will be handled by the JPEG library error mechanism; the second * table pointer is used for this purpose. * * First table includes all errors generated by JPEG library itself. * Error code 0 is reserved for a "no such error string" message. */ const char * const * jpeg_message_table; /* Library errors */ int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ /* Second table can be added by application (see cjpeg/djpeg for example). * It contains strings numbered first_addon_message..last_addon_message. */ const char * const * addon_message_table; /* Non-library errors */ int first_addon_message; /* code for first string in addon table */ int last_addon_message; /* code for last string in addon table */ }; /* Progress monitor object */ struct jpeg_progress_mgr { JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); long pass_counter; /* work units completed in this pass */ long pass_limit; /* total number of work units in this pass */ int completed_passes; /* passes completed so far */ int total_passes; /* total number of passes expected */ }; /* Data destination object for compression */ struct jpeg_destination_mgr { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ JMETHOD(void, init_destination, (j_compress_ptr cinfo)); JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); JMETHOD(void, term_destination, (j_compress_ptr cinfo)); }; /* Data source object for decompression */ struct jpeg_source_mgr { const JOCTET * next_input_byte; /* => next byte to read from buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */ JMETHOD(void, init_source, (j_decompress_ptr cinfo)); JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo)); JMETHOD(void, term_source, (j_decompress_ptr cinfo)); }; /* Memory manager object. * Allocates "small" objects (a few K total), "large" objects (tens of K), * and "really big" objects (virtual arrays with backing store if needed). * The memory manager does not allow individual objects to be freed; rather, * each created object is assigned to a pool, and whole pools can be freed * at once. This is faster and more convenient than remembering exactly what * to free, especially where malloc()/free() are not too speedy. * NB: alloc routines never return NULL. They exit to error_exit if not * successful. */ #define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ #define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ #define JPOOL_NUMPOOLS 2 typedef struct jvirt_sarray_control * jvirt_sarray_ptr; typedef struct jvirt_barray_control * jvirt_barray_ptr; struct jpeg_memory_mgr { /* Method pointers */ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows)); JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows)); JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows, JDIMENSION unitheight)); JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION unitheight)); JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JDIMENSION start_row, boolean writable)); JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, jvirt_barray_ptr ptr, JDIMENSION start_row, boolean writable)); JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); JMETHOD(void, self_destruct, (j_common_ptr cinfo)); /* Limit on memory allocation for this JPEG object. (Note that this is * merely advisory, not a guaranteed maximum; it only affects the space * used for virtual-array buffers.) May be changed by outer application * after creating the JPEG object. */ long max_memory_to_use; }; /* Declarations for routines called by application. * The JPP macro hides prototype parameters from compilers that can't cope. * Note JPP requires double parentheses. */ #ifdef HAVE_PROTOTYPES #define JPP(arglist) arglist #else #define JPP(arglist) () #endif /* Short forms of external names for systems with brain-damaged linkers. * We shorten external names to be unique in the first six letters, which * is good enough for all known systems. * (If your compiler itself needs names to be unique in less than 15 * characters, you are out of luck. Get a better compiler.) */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_std_error jStdError #define jpeg_create_compress jCreaCompress #define jpeg_create_decompress jCreaDecompress #define jpeg_destroy_compress jDestCompress #define jpeg_destroy_decompress jDestDecompress #define jpeg_stdio_dest jStdDest #define jpeg_stdio_src jStdSrc #define jpeg_set_defaults jSetDefaults #define jpeg_set_colorspace jSetColorspace #define jpeg_set_quality jSetQuality #define jpeg_set_linear_quality jSetLQuality #define jpeg_add_quant_table jAddQuantTable #define jpeg_quality_scaling jQualityScaling #define jpeg_suppress_tables jSuppressTables #define jpeg_alloc_quant_table jAlcQTable #define jpeg_alloc_huff_table jAlcHTable #define jpeg_start_compress jStrtCompress #define jpeg_write_scanlines jWrtScanlines #define jpeg_finish_compress jFinCompress #define jpeg_write_tables jWrtTables #define jpeg_read_header jReadHeader #define jpeg_start_decompress jStrtDecompress #define jpeg_read_scanlines jReadScanlines #define jpeg_finish_decompress jFinDecompress #define jpeg_calc_output_dimensions jCalcDimensions #define jpeg_abort_compress jAbrtCompress #define jpeg_abort_decompress jAbrtDecompress #define jpeg_abort jAbort #define jpeg_destroy jDestroy #define jpeg_resync_to_restart jResyncRestart #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Default error-management setup */ EXTERN struct jpeg_error_mgr *jpeg_std_error JPP((struct jpeg_error_mgr *err)); /* Initialization and destruction of JPEG compression objects */ /* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx */ EXTERN void jpeg_create_compress JPP((j_compress_ptr cinfo)); EXTERN void jpeg_create_decompress JPP((j_decompress_ptr cinfo)); EXTERN void jpeg_destroy_compress JPP((j_compress_ptr cinfo)); EXTERN void jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); /* Standard data source and destination managers: stdio streams. */ /* Caller is responsible for opening the file before and closing after. */ EXTERN void jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN void jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); /* Default parameter setup for compression */ EXTERN void jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ EXTERN void jpeg_set_colorspace JPP((j_compress_ptr cinfo, J_COLOR_SPACE colorspace)); EXTERN void jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, boolean force_baseline)); EXTERN void jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); EXTERN void jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline)); EXTERN int jpeg_quality_scaling JPP((int quality)); EXTERN void jpeg_suppress_tables JPP((j_compress_ptr cinfo, boolean suppress)); EXTERN JQUANT_TBL * jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); EXTERN JHUFF_TBL * jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); /* Main entry points for compression */ EXTERN void jpeg_start_compress JPP((j_compress_ptr cinfo, boolean write_all_tables)); EXTERN JDIMENSION jpeg_write_scanlines JPP((j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines)); EXTERN void jpeg_finish_compress JPP((j_compress_ptr cinfo)); /* Alternate compression function: just write an abbreviated table file */ EXTERN void jpeg_write_tables JPP((j_compress_ptr cinfo)); /* Decompression startup: read start of JPEG datastream to see what's there */ EXTERN int jpeg_read_header JPP((j_decompress_ptr cinfo, boolean require_image)); /* Return value is one of: */ #define JPEG_HEADER_OK 0 /* Found valid image datastream */ #define JPEG_HEADER_TABLES_ONLY 1 /* Found valid table-specs-only datastream */ #define JPEG_SUSPENDED 2 /* Had to suspend before end of headers */ /* If you pass require_image = TRUE (normal case), you need not check for * a TABLES_ONLY return code; an abbreviated file will cause an error exit. * JPEG_SUSPENDED is only possible if you use a data source module that can * give a suspension return (the stdio source module doesn't). */ /* Main entry points for decompression */ EXTERN void jpeg_start_decompress JPP((j_decompress_ptr cinfo)); EXTERN JDIMENSION jpeg_read_scanlines JPP((j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines)); EXTERN boolean jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); /* Precalculate output dimensions for current decompression parameters. */ EXTERN void jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* If you choose to abort compression or decompression before completing * jpeg_finish_(de)compress, then you need to clean up to release memory, * temporary files, etc. You can just call jpeg_destroy_(de)compress * if you're done with the JPEG object, but if you want to clean it up and * reuse it, call this: */ EXTERN void jpeg_abort_compress JPP((j_compress_ptr cinfo)); EXTERN void jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); /* Generic versions of jpeg_abort and jpeg_destroy that work on either * flavor of JPEG object. These may be more convenient in some places. */ EXTERN void jpeg_abort JPP((j_common_ptr cinfo)); EXTERN void jpeg_destroy JPP((j_common_ptr cinfo)); /* Default restart-marker-resync procedure for use by data source modules */ EXTERN boolean jpeg_resync_to_restart JPP((j_decompress_ptr cinfo)); /* These marker codes are exported since applications and data source modules * are likely to want to use them. */ #define JPEG_RST0 0xD0 /* RST0 marker code */ #define JPEG_EOI 0xD9 /* EOI marker code */ #define JPEG_APP0 0xE0 /* APP0 marker code */ #define JPEG_COM 0xFE /* COM marker code */ /* If we have a brain-damaged compiler that emits warnings (or worse, errors) * for structure definitions that are never filled in, keep it quiet by * supplying dummy definitions for the various substructures. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ struct jvirt_sarray_control { long dummy; }; struct jvirt_barray_control { long dummy; }; struct jpeg_comp_master { long dummy; }; struct jpeg_c_main_controller { long dummy; }; struct jpeg_c_prep_controller { long dummy; }; struct jpeg_c_coef_controller { long dummy; }; struct jpeg_marker_writer { long dummy; }; struct jpeg_color_converter { long dummy; }; struct jpeg_downsampler { long dummy; }; struct jpeg_forward_dct { long dummy; }; struct jpeg_entropy_encoder { long dummy; }; struct jpeg_decomp_master { long dummy; }; struct jpeg_d_main_controller { long dummy; }; struct jpeg_d_coef_controller { long dummy; }; struct jpeg_d_post_controller { long dummy; }; struct jpeg_marker_reader { long dummy; }; struct jpeg_entropy_decoder { long dummy; }; struct jpeg_inverse_dct { long dummy; }; struct jpeg_upsampler { long dummy; }; struct jpeg_color_deconverter { long dummy; }; struct jpeg_color_quantizer { long dummy; }; #endif /* JPEG_INTERNALS */ #endif /* INCOMPLETE_TYPES_BROKEN */ /* * The JPEG library modules define JPEG_INTERNALS before including this file. * The internal structure declarations are read only when that is true. * Applications using the library should not include jpegint.h, but may wish * to include jerror.h. */ #ifdef JPEG_INTERNALS #include "jpegint.h" /* fetch private declarations */ #include "jerror.h" /* fetch error codes too */ #endif \ No newline at end of file diff --git a/Headers/jversion.h b/Headers/jversion.h new file mode 100644 index 0000000..1591ae5 --- /dev/null +++ b/Headers/jversion.h @@ -0,0 +1 @@ +/* * jversion.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains software version identification. */ #define JVERSION "5alpha2 4-May-94" #define JCOPYRIGHT "Copyright (C) 1994, Thomas G. Lane" \ No newline at end of file diff --git a/Independent JPEG Group/Changed/jconfig.h b/Independent JPEG Group/Changed/jconfig.h new file mode 100644 index 0000000..e6f6b63 --- /dev/null +++ b/Independent JPEG Group/Changed/jconfig.h @@ -0,0 +1 @@ +/* * jconfig.doc * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file documents the configuration options that are required to * customize the JPEG software for a particular system. * * The actual configuration options for a particular installation are stored * in jconfig.h. On many machines, jconfig.h can be generated automatically * or copied from one of the "canned" jconfig files that we supply. But if * you need to generate a jconfig.h file by hand, this file tells you how. * * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. * EDIT A COPY NAMED JCONFIG.H. */ /* * These symbols indicate the properties of your machine or compiler. * #define the symbol if yes, #undef it if no. */ /* Does your compiler support function prototypes? * (If not, you also need to use ansi2knr, see install.doc) */ #define HAVE_PROTOTYPES /* Does your compiler support the declaration "unsigned char" ? * How about "unsigned short" ? */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define "const" as empty if your compiler doesn't know the "const" keyword. */ /* #define const */ /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. */ #undef CHAR_IS_UNSIGNED /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDDEF_H /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDLIB_H /* Define this if your system does not have an ANSI/SysV , * but does have a BSD-style . */ #undef NEED_BSD_STRINGS /* Define this if your system does not provide typedef size_t in any of the * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in * instead. */ #undef NEED_SYS_TYPES_H /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #undef NEED_FAR_POINTERS /* Define this if your linker needs global names to be unique in less * than the first 15 characters. */ #undef NEED_SHORT_EXTERNAL_NAMES /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you * actually get "missing structure definition" warnings or errors while * compiling the JPEG code. */ #undef INCOMPLETE_TYPES_BROKEN /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS has been defined. */ #ifdef JPEG_INTERNALS /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ /* * The remaining options do not affect the JPEG library proper, * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). * Other applications can ignore these. */ #ifdef JPEG_CJPEG_DJPEG /* These defines indicate which image (non-JPEG) file formats are allowed. */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of cjpeg.c or djpeg.c. */ #undef TWO_FILE_COMMANDLINE /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #undef NEED_SIGNAL_CATCHER /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/Changed/jdcolor.c b/Independent JPEG Group/Changed/jdcolor.c new file mode 100644 index 0000000..4a484a1 --- /dev/null +++ b/Independent JPEG Group/Changed/jdcolor.c @@ -0,0 +1 @@ +/* * jdcolor.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains output colorspace conversion routines. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private subobject */ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ } my_color_deconverter; typedef my_color_deconverter * my_cconvert_ptr; /**************** YCbCr -> RGB conversion: most common case **************/ /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * R = Y + 1.40200 * Cr * G = Y - 0.34414 * Cb - 0.71414 * Cr * B = Y + 1.77200 * Cb * where Cb and Cr represent the incoming values less MAXJSAMPLE/2. * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * Notice that Y, being an integral input, does not contribute any fraction * so it need not participate in the rounding. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. * The Cr=>R and Cb=>B values can be rounded to integers in advance; the * values for the G calculation are left scaled up, since we must add them * together before rounding. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. */ METHODDEF void ycc_rgb_start (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; INT32 i, x2; SHIFT_TEMPS cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0; i <= MAXJSAMPLE; i++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - MAXJSAMPLE/2 */ x2 = 2*i - MAXJSAMPLE; /* twice x */ /* Cr=>R value is nearest int to 1.40200 * x */ cconvert->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200/2) * x2 + ONE_HALF, SCALEBITS); /* Cb=>B value is nearest int to 1.77200 * x */ cconvert->Cb_b_tab[i] = (int) RIGHT_SHIFT(FIX(1.77200/2) * x2 + ONE_HALF, SCALEBITS); /* Cr=>G value is scaled-up -0.71414 * x */ cconvert->Cr_g_tab[i] = (- FIX(0.71414/2)) * x2; /* Cb=>G value is scaled-up -0.34414 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF; } } /* * Convert some rows of samples to the output colorspace. * * Note that we change from noninterleaved, one-plane-per-component format * to interleaved-pixel format. The output buffer is therefore three times * as wide as the input buffer. * A starting row offset is provided only for the input buffer. The caller * can easily adjust the passed output_buf value to accommodate any row * offset required on that side. */ METHODDEF void ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Note: if the inputs were computed directly from RGB values, * range-limiting would be unnecessary here; but due to possible * noise in the DCT/IDCT phase, we do need to apply range limits. */ #ifdef SLOW outptr[1] = range_limit[y + Crrtab[cr]]; /* red */ outptr[2] = range_limit[y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr[3] = range_limit[y + Cbbtab[cb]]; /* blue */ #else *(long *)outptr = (range_limit[y + Crrtab[cr]] << 16) + (range_limit[y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))] << 8) + range_limit[y + Cbbtab[cb]]; outptr += 4; } } } /**************** Cases other than YCbCr -> RGB **************/ /* * Color conversion for no colorspace change: just copy the data, * converting from separate-planes to interleaved representation. */ METHODDEF void null_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register JSAMPROW inptr, outptr; register JDIMENSION count; register int num_components = cinfo->output_components; JDIMENSION num_cols = cinfo->output_width; int ci; while (--num_rows >= 0) { for (ci = 0; ci < num_components; ci++) { inptr = input_buf[ci][input_row]; outptr = output_buf[0] + ci; for (count = num_cols; count > 0; count--) { *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ outptr += num_components; } } input_row++; output_buf++; } } /* * Color conversion for grayscale: just copy the data. * This also works for YCbCr -> grayscale conversion, in which * we just copy the Y (luminance) component and ignore chrominance. */ METHODDEF void grayscale_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, num_rows, cinfo->output_width); } /* * Adobe-style YCCK->CMYK conversion. * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same * conversion as above, while passing K (black) unchanged. * We assume ycc_rgb_start has been called. */ METHODDEF void ycck_cmyk_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; inptr3 = input_buf[3][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Note: if the inputs were computed directly from RGB values, * range-limiting would be unnecessary here; but due to possible * noise in the DCT/IDCT phase, we do need to apply range limits. */ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ outptr += 4; } } } /* * Empty method for start_pass. */ METHODDEF void null_method (j_decompress_ptr cinfo) { /* no work needed */ } /* * Module initialization routine for output colorspace conversion. */ GLOBAL void jinit_color_deconverter (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert; int ci; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_deconverter)); cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_RGB: case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->num_components < 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; } /* Set out_color_components and conversion method based on requested space. * Also clear the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; if (cinfo->jpeg_color_space == JCS_GRAYSCALE || cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->cur_comp_info[ci]->component_needed = FALSE; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: cinfo->out_color_components = 3; if (cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.start_pass = ycc_rgb_start; cconvert->pub.color_convert = ycc_rgb_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: cinfo->out_color_components = 4; if (cinfo->jpeg_color_space == JCS_YCCK) { cconvert->pub.start_pass = ycc_rgb_start; cconvert->pub.color_convert = ycck_cmyk_convert; } else if (cinfo->jpeg_color_space == JCS_CMYK) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; default: /* Permit null conversion to same output space */ if (cinfo->out_color_space == cinfo->jpeg_color_space) { cinfo->out_color_components = cinfo->num_components; cconvert->pub.color_convert = null_convert; } else /* unsupported non-null conversion */ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; } if (cinfo->quantize_colors) cinfo->output_components = 1; /* single colormapped output component */ else cinfo->output_components = cinfo->out_color_components; } \ No newline at end of file diff --git a/Independent JPEG Group/Changed/jmorecfg.h b/Independent JPEG Group/Changed/jmorecfg.h new file mode 100644 index 0000000..5706db3 --- /dev/null +++ b/Independent JPEG Group/Changed/jmorecfg.h @@ -0,0 +1 @@ +/* * jmorecfg.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains additional configuration options that customize the * JPEG software for special applications or support machine-dependent * optimizations. Most users will not need to touch this file. */ /* * Define BITS_IN_JSAMPLE as either * 8 for 8-bit sample values (the usual setting) * 12 for 12-bit sample values * Only 8 and 12 are legal data precisions for lossy JPEG according to the * JPEG standard, and the IJG code does not support anything else! * We do not support run-time selection of data precision, sorry. */ #define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ /* * Maximum number of components (color channels) allowed in JPEG image. * To meet the letter of the JPEG spec, set this to 255. However, darn * few applications need more than 4 channels (maybe 5 for CMYK + alpha * mask). We recommend 10 as a reasonable compromise; use 4 if you are * really short on memory. (Each allowed component costs a hundred or so * bytes of storage, whether actually used in an image or not.) */ #define MAX_COMPONENTS 10 /* maximum number of image components */ /* * Basic data types. * You may need to change these if you have a machine with unusual data * type sizes; for example, "char" not 8 bits, "short" not 16 bits, * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, * but it had better be at least 16. */ /* Representation of a single sample (pixel element value). * We frequently allocate large arrays of these, so it's important to keep * them small. But if you have memory to burn and access to char or short * arrays is very slow on your hardware, you might want to change these. */ #if BITS_IN_JSAMPLE == 8 /* JSAMPLE should be the smallest type that will hold the values 0..255. * You can use a signed char by having GETJSAMPLE mask it with 0xFF. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JSAMPLE; #ifdef CHAR_IS_UNSIGNED #define GETJSAMPLE(value) (value) #else #define GETJSAMPLE(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ #define MAXJSAMPLE 255 #define CENTERJSAMPLE 128 #endif /* BITS_IN_JSAMPLE == 8 */ #if BITS_IN_JSAMPLE == 12 /* JSAMPLE should be the smallest type that will hold the values 0..4095. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) (value) #define MAXJSAMPLE 4095 #define CENTERJSAMPLE 2048 #endif /* BITS_IN_JSAMPLE == 12 */ /* Representation of a DCT frequency coefficient. * This should be a signed value of at least 16 bits; "short" is usually OK. * Again, we allocate large arrays of these, but you can change to int * if you have memory to burn and "short" is really slow. */ typedef short JCOEF; /* Compressed datastreams are represented as arrays of JOCTET. * These must be EXACTLY 8 bits wide, at least once they are written to * external storage. Note that when using the stdio data source/destination * managers, this is also the data type passed to fread/fwrite. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JOCTET; #define GETJOCTET(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JOCTET; #ifdef CHAR_IS_UNSIGNED #define GETJOCTET(value) (value) #else #define GETJOCTET(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* These typedefs are used for various table entries and so forth. * They must be at least as wide as specified; but making them too big * won't cost a huge amount of memory, so we don't provide special * extraction code like we did for JSAMPLE. (In other words, these * typedefs live at a different point on the speed/space tradeoff curve.) */ /* UINT8 must hold at least the values 0..255. */ #ifdef HAVE_UNSIGNED_CHAR #if defined(powerc) || defined(__powerc) // CHANGED! typedef unsigned long UINT8; // CHANGED! #else // CHANGED! typedef unsigned short UINT8; #endif // CHANGED! #else /* not HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char UINT8; #else /* not CHAR_IS_UNSIGNED */ typedef short UINT8; #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* UINT16 must hold at least the values 0..65535. */ #ifdef HAVE_UNSIGNED_SHORT #if defined(powerc) || defined(__powerc) // CHANGED! typedef unsigned long UINT16; // CHANGED! #else // CHANGED! typedef unsigned short UINT16; #endif // CHANGED! #else /* not HAVE_UNSIGNED_SHORT */ typedef unsigned int UINT16; #endif /* HAVE_UNSIGNED_SHORT */ /* INT16 must hold at least the values -32768..32767. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ #if defined(powerc) || defined(__powerc) // CHANGED! typedef long INT16; // CHANGED! #else // CHANGED! typedef short INT16; #endif // CHANGED! #endif /* INT32 must hold at least signed 32-bit values. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ typedef long INT32; #endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore * "unsigned int" is sufficient on all machines. However, if you need to * handle larger images and you don't mind deviating from the spec, you * can change this datatype. */ typedef unsigned int JDIMENSION; #define JPEG_MAX_DIMENSION 65500 /* a tad under 64K to prevent overflows */ /* These defines are used in all function definitions and extern declarations. * You could modify them if you need to change function linkage conventions. * Another application is to make all functions global for use with debuggers * or code profilers that require it. */ #define METHODDEF static /* a function called through method pointers */ #define LOCAL static /* a function used only in its module */ #define GLOBAL /* a function referenced thru EXTERNs */ #define EXTERN extern /* a reference to a GLOBAL function */ /* Here is the pseudo-keyword for declaring pointers that must be "far" * on 80x86 machines. Most of the specialized coding for 80x86 is handled * by just saying "FAR *" where such a pointer is needed. In a few places * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif /* * On a few systems, type boolean and/or its values FALSE, TRUE may appear * in standard header files. Or you may have conflicts with application- * specific header files that you want to include together with these files. * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. */ #ifndef HAVE_BOOLEAN typedef int boolean; #endif #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. */ #ifdef JPEG_INTERNALS #define JPEG_INTERNAL_OPTIONS #endif #ifdef JPEG_INTERNAL_OPTIONS /* * These defines indicate whether to include various optional functions. * Undefining some of these symbols will produce a smaller but less capable * library. Note that you can leave certain source files out of the * compilation/linking process if you've #undef'd the corresponding symbols. * (You may HAVE to do that if your compiler doesn't like null source files.) */ /* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ /* Encoder capability options: */ #undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #undef C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? (NYI) */ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit * precision, so jchuff.c normally uses entropy optimization to compute * usable tables for higher precision. If you don't want to do optimization, * you'll have to supply different default Huffman tables. */ #undef INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ /* Decoder capability options: */ #undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #undef D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #undef BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */ #undef QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ // CHANGED! #undef'ed #undef QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ // CHANGED! #undef'ed /* more capability options later, no doubt */ /* If your compiler supports inline functions, define INLINE * as the inline keyword; otherwise define it as empty. */ #ifndef INLINE #ifdef __GNUC__ /* for instance, GNU C knows about inline */ #define INLINE __inline__ #endif #ifndef INLINE #define INLINE /* default is to define it as empty */ #endif #endif /* Typedef for multiplying quantized coefficients by pre-IDCT multipliers. * Must be a signed type. Use short if short*short is faster than int*int. */ #if BITS_IN_JSAMPLE == 8 typedef short MULTIPLIER; /* may want short on some machines */ // CHANGED! int -> short #else typedef INT32 MULTIPLIER; /* need more than 16 bits in this case */ #endif #endif /* JPEG_INTERNAL_OPTIONS */ \ No newline at end of file diff --git a/Independent JPEG Group/JPEGLib.o b/Independent JPEG Group/JPEGLib.o new file mode 100644 index 0000000000000000000000000000000000000000..ccdfe9b11492842ce206f29b79cde4ddcf0e8558 GIT binary patch literal 74326 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 DGVco@ literal 0 HcmV?d00001 diff --git a/Independent JPEG Group/JPEGLib.xcoff b/Independent JPEG Group/JPEGLib.xcoff new file mode 100644 index 0000000000000000000000000000000000000000..62142bcbf37c12caf4872cfa8e980ccd228eb859 GIT binary patch literal 135538 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 literal 0 HcmV?d00001 diff --git a/Independent JPEG Group/JPEGLib.µ b/Independent JPEG Group/JPEGLib.µ new file mode 100644 index 0000000000000000000000000000000000000000..12f5e8507d067e68425e465d41521d0fb0ea975a GIT binary patch literal 141949 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

    QdjwJmxUy<-Xd)uSAMdCl#AI~ik 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 literal 0 HcmV?d00001 diff --git a/Independent JPEG Group/Makefile.TXT b/Independent JPEG Group/Makefile.TXT new file mode 100644 index 0000000..9b662a3 --- /dev/null +++ b/Independent JPEG Group/Makefile.TXT @@ -0,0 +1 @@ +#-------------------------------------------------------------------- # # JPEGView MakeFile # # Created: 23 Jan 94 # Modified: 17 Mar 94 # #-------------------------------------------------------------------- # Step 1: Define the variables #-------------------------------------------------------------------- #--------------------------------- General application variables LibName = JPEGLib #--------------------------------- Directories and dependencies ObjDir = :Objects: CSrcDir = : "{ObjDir}" Ä "{CSrcDir}" #--------------------------------- Include paths IncludePaths = -i "{MPW}"Interfaces:PPCCIncludes: #--------------------------------- Object list variables PPCObjects = "{ObjDir}"jcapi.c.ppc.o ¶ "{ObjDir}"jccoefct.c.ppc.o ¶ "{ObjDir}"jccolor.c.ppc.o ¶ "{ObjDir}"jcdctmgr.c.ppc.o ¶ "{ObjDir}"jchuff.c.ppc.o ¶ "{ObjDir}"jcmainct.c.ppc.o ¶ "{ObjDir}"jcmarker.c.ppc.o ¶ "{ObjDir}"jcmaster.c.ppc.o ¶ "{ObjDir}"jcomapi.c.ppc.o ¶ "{ObjDir}"jcparam.c.ppc.o ¶ "{ObjDir}"jcprepct.c.ppc.o ¶ "{ObjDir}"jcsample.c.ppc.o ¶ "{ObjDir}"jdapi.c.ppc.o ¶ "{ObjDir}"jdatasrc.c.ppc.o ¶ "{ObjDir}"jdatadst.c.ppc.o ¶ "{ObjDir}"jdcoefct.c.ppc.o ¶ "{ObjDir}"jdcolor.c.ppc.o ¶ "{ObjDir}"jddctmgr.c.ppc.o ¶ "{ObjDir}"jdhuff.c.ppc.o ¶ "{ObjDir}"jdmainct.c.ppc.o ¶ "{ObjDir}"jdmarker.c.ppc.o ¶ "{ObjDir}"jdmaster.c.ppc.o ¶ "{ObjDir}"jdpostct.c.ppc.o ¶ "{ObjDir}"jdsample.c.ppc.o ¶ "{ObjDir}"jerror.c.ppc.o ¶ "{ObjDir}"jutils.c.ppc.o ¶ "{ObjDir}"jfdctllm.c.ppc.o ¶ "{ObjDir}"jidctllm.c.ppc.o ¶ "{ObjDir}"jidctred.c.ppc.o ¶ "{ObjDir}"jquant1.c.ppc.o ¶ "{ObjDir}"jquant2.c.ppc.o ¶ "{ObjDir}"jmemmgr.c.ppc.o ¶ "{ObjDir}"jmemnobs.c.ppc.o 68kObjects = "{ObjDir}"jcapi.c.68k.o ¶ "{ObjDir}"jccoefct.c.68k.o ¶ "{ObjDir}"jccolor.c.68k.o ¶ "{ObjDir}"jcdctmgr.c.68k.o ¶ "{ObjDir}"jchuff.c.68k.o ¶ "{ObjDir}"jcmainct.c.68k.o ¶ "{ObjDir}"jcmarker.c.68k.o ¶ "{ObjDir}"jcmaster.c.68k.o ¶ "{ObjDir}"jcomapi.c.68k.o ¶ "{ObjDir}"jcparam.c.68k.o ¶ "{ObjDir}"jcprepct.c.68k.o ¶ "{ObjDir}"jcsample.c.68k.o ¶ "{ObjDir}"jdapi.c.68k.o ¶ "{ObjDir}"jdatasrc.c.68k.o ¶ "{ObjDir}"jdatadst.c.68k.o ¶ "{ObjDir}"jdcoefct.c.68k.o ¶ "{ObjDir}"jdcolor.c.68k.o ¶ "{ObjDir}"jddctmgr.c.68k.o ¶ "{ObjDir}"jdhuff.c.68k.o ¶ "{ObjDir}"jdmainct.c.68k.o ¶ "{ObjDir}"jdmarker.c.68k.o ¶ "{ObjDir}"jdmaster.c.68k.o ¶ "{ObjDir}"jdpostct.c.68k.o ¶ "{ObjDir}"jdsample.c.68k.o ¶ "{ObjDir}"jerror.c.68k.o ¶ "{ObjDir}"jutils.c.68k.o ¶ "{ObjDir}"jfdctllm.c.68k.o ¶ "{ObjDir}"jidctllm.c.68k.o ¶ "{ObjDir}"jidctred.c.68k.o ¶ "{ObjDir}"jquant1.c.68k.o ¶ "{ObjDir}"jquant2.c.68k.o ¶ "{ObjDir}"jmemmgr.c.68k.o ¶ "{ObjDir}"jmemnobs.c.68k.o #--------------------------------- Compiler options PPCCOptions = -opt speed -appleext on {IncludePaths} 68kCOptions = -mbg off -sym off -r -mc68020 -opt speed {IncludePaths} #-------------------------------------------------------------------- # Step 2: Compile dependencies for PPC #-------------------------------------------------------------------- #--------------------------------- The library itself {LibName}.xcoff ÄÄ {PPCObjects} PPCLink {PPCObjects} -xm library -o "{LinkDir}"{LibName}.xcoff #--------------------------------- Source files .c.ppc.o Ä .c PPCC "{DepDir}""{default}".c -o "{TargDir}""{default}".c.ppc.o {PPCCOptions} #-------------------------------------------------------------------- # Step 3: Compile dependencies for 68k #-------------------------------------------------------------------- #--------------------------------- The application itself {LibName}.o ÄÄ {68kObjects} Lib {68kObjects} -o {LibName}.o #--------------------------------- Source files .c.68k.o Ä .c C "{DepDir}""{default}".c -o "{TargDir}""{default}".c.68k.o -s "{default}" {68kCOptions} \ No newline at end of file diff --git a/Independent JPEG Group/README.TXT b/Independent JPEG Group/README.TXT new file mode 100644 index 0000000..6e0dee6 --- /dev/null +++ b/Independent JPEG Group/README.TXT @@ -0,0 +1 @@ +The Independent JPEG Group's JPEG software ========================================== README for release 5alpha2 of 4-May-94 ====================================== This archive contains an alpha-test release of the Independent JPEG Group's free JPEG software. THIS CODE IS NOT INTENDED FOR WIDESPREAD USE. It has some limitations and, no doubt, a few bugs. If you want something more trustworthy, please see the latest official release (available as described under ARCHIVE LOCATIONS, below). This software is the work of Tom Lane, Philip Gladstone, Luis Ortiz, Lee Crocker, George Phillips, Ge' Weijers, and other members of the Independent JPEG Group. DOCUMENTATION ROADMAP ===================== Please read at least the files install.doc (installation instructions) and usage.doc (usage instructions). Useful information can also be found in the JPEG FAQ (Frequently Asked Questions) article; see ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. This file contains the following sections: OVERVIEW General description of JPEG and the IJG software. LEGAL ISSUES Copyright, lack of warranty, terms of distribution. (READ THIS) REFERENCES Where to learn more about JPEG. ARCHIVE LOCATIONS Where to find newer versions of this software. RELATED SOFTWARE Other stuff you should get. FILE FORMAT WARS Software *not* to get. TO DO Plans for future IJG releases. Other documentation files in the distribution are: User documentation: install.doc How to configure and install the IJG software. usage.doc cjpeg/djpeg usage instructions. cjpeg.1 Unix-style man page for cjpeg (same info as usage.doc). djpeg.1 Unix-style man page for djpeg (same info as usage.doc). change.log Version-to-version change highlights. Programmer and internal documentation: libjpeg.doc How to use the JPEG library in your own programs. example.c Sample code for calling JPEG library. structure.doc Overview of the JPEG library's internal structure. filelist.doc Road map of IJG files. coderules.doc Coding style rules. Please read if you contribute code to IJG. If you want to understand how the JPEG code works, we suggest reading one or more of the REFERENCES, then looking at the documentation files (in roughly the order listed) before diving into the code. OVERVIEW ======== This is an early test release of the rewritten IJG library, intended for the hardy and adventurous only. Consider yourself warned. There's still a good deal of missing functionality in this release (see change.log for the current status). Still, the software is quite useful within its limits, and it is noticeably faster than version 4. ---------- This archive contains C software to implement JPEG image compression and decompression. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and gray-scale images. JPEG is intended for compressing "real-world" scenes; cartoons and other non-realistic images are not its strong suit. JPEG is lossy, meaning that the output image is not necessarily identical to the input image. Hence you must not use JPEG if you have to have identical output bits. However, on typical images of real-world scenes, very good compression levels can be obtained with no visible change, and amazingly high compression levels are possible if you can tolerate a low-quality image. For more details, see the references, or just experiment with various compression settings. We provide a set of library routines for reading and writing JPEG image files, plus two simple applications "cjpeg" and "djpeg", which use the library to perform conversion between JPEG and some other popular image file formats. The library is intended to be reused in other applications. This software implements JPEG baseline and extended-sequential compression processes. Provision is made for supporting all variants of these processes, although some uncommon parameter settings aren't implemented yet. For legal reasons, we are not distributing code for the arithmetic-coding process; see LEGAL ISSUES. At present we have made no provision for supporting the progressive, hierarchical, or lossless processes defined in the standard. (Support for progressive mode may be offered in a future release.) In order to support file conversion and viewing software, we have included considerable functionality beyond the bare JPEG coding/decoding capability; for example, the color quantization modules are not strictly part of JPEG decoding, but they are essential for output to colormapped file formats or colormapped displays. These extra functions can be compiled out of the library if not required for a particular application. The emphasis in designing this software has been on achieving portability and flexibility, while also making it fast enough to be useful. In particular, the software is not intended to be read as a tutorial on JPEG. (See the REFERENCES section for introductory material.) While we hope that the entire package will someday be industrial-strength code, much remains to be done in performance tuning and in improving the capabilities of individual modules. We welcome the use of this software as a component of commercial products. No royalty is required, but we do ask for an acknowledgement in product documentation, as described under LEGAL ISSUES. LEGAL ISSUES ============ The authors make NO WARRANTY or representation, either express or implied, with respect to this software, its quality, accuracy, merchantability, or fitness for a particular purpose. This software is provided "AS IS", and you, its user, assume the entire risk as to its quality and accuracy. This software is copyright (C) 1991, 1992, 1993, 1994, Thomas G. Lane. All Rights Reserved except as specified below. Permission is hereby granted to use, copy, modify, and distribute this software (or portions thereof) for any purpose, without fee, subject to these conditions: (1) If any part of the source code for this software is distributed, then this README file must be included, with this copyright and no-warranty notice unaltered; and any additions, deletions, or changes to the original files must be clearly indicated in accompanying documentation. (2) If only executable code is distributed, then the accompanying documentation must state that "this software is based in part on the work of the Independent JPEG Group". (3) Permission for use of this software is granted only if the user accepts full responsibility for any undesirable consequences; the authors accept NO LIABILITY for damages of any kind. Permission is NOT granted for the use of any IJG author's name or company name in advertising or publicity relating to this software or products derived from it. This software may be referred to only as "the Independent JPEG Group's software". We specifically permit and encourage the use of this software as the basis of commercial products, provided that all warranty or liability claims are assumed by the product vendor. ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. ansi2knr.c is NOT covered by the above copyright and conditions, but instead by the usual distribution terms of the Free Software Foundation; principally, that you must include source code if you redistribute it. (See the file ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part of any program generated from the IJG code, this does not limit you more than the foregoing paragraphs do. The configuration script "configure" was produced by GNU Autoconf. Again, the FSF copyright terms apply only to configure, not to the IJG code. It appears that the arithmetic coding option of the JPEG spec is covered by patents owned by IBM, AT&T, and Mitsubishi. Hence arithmetic coding cannot legally be used without obtaining one or more licenses. For this reason, support for arithmetic coding has been removed from the free JPEG software. (Since arithmetic coding provides only a marginal gain over the unpatented Huffman mode, it is unlikely that very many implementations will support it.) So far as we are aware, there are no patent restrictions on the remaining code. We are required to state that "The Graphics Interchange Format(c) is the Copyright property of CompuServe Incorporated. GIF(sm) is a Service Mark property of CompuServe Incorporated." REFERENCES ========== We highly recommend reading one or more of these references before trying to understand the innards of any JPEG software. The best short technical introduction to the JPEG compression algorithm is Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. (Adjacent articles in that issue discuss MPEG motion picture compression, applications of JPEG, and related topics.) If you don't have the CACM issue handy, a PostScript file containing a revised version of the article is available at ftp.uu.net, graphics/jpeg/wallace.ps.Z. The file (actually a preprint for an article to appear in IEEE Trans. Consumer Electronics) omits the sample images that appeared in CACM, but it includes corrections and some added material. Note: the Wallace article is copyright ACM and IEEE, and it may not be used for commercial purposes. A somewhat less technical, more leisurely introduction to JPEG can be found in "The Data Compression Book" by Mark Nelson, published by M&T Books (Redwood City, CA), 1991, ISBN 1-55851-216-0. This book provides good explanations and example C code for a multitude of compression methods including JPEG. It is an excellent source if you are comfortable reading C code but don't know much about data compression in general. The book's JPEG sample code is far from industrial-strength, but when you are ready to look at a full implementation, you've got one here... The best full description of JPEG is the textbook "JPEG Still Image Data Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1. Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG standards (DIS 10918-1 and draft DIS 10918-2). This is by far the most complete exposition of JPEG in existence, and we highly recommend it. The JPEG standard itself is not available electronically; you must order a paper copy through ISO. (Unless you feel a need to own a certified official copy, we recommend buying the Pennebaker and Mitchell book instead; it's much cheaper and includes a great deal of useful explanatory material.) In the US, copies of the standard may be ordered from ANSI Sales at (212) 642-4900, or from Global Engineering Documents at (800) 854-7179. (Global will take credit card orders, ANSI won't.) It's not cheap: as of 1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% shipping/handling. The standard is divided into two parts, Part 1 being the actual specification, while Part 2 covers compliance testing methods. Part 1 is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 1: Requirements and guidelines" and has document number ISO/IEC IS 10918-1. As of late 1993, Part 2 is still at Draft International Standard status. It is titled "Digital Compression and Coding of Continuous-tone Still Images, Part 2: Compliance testing" and has document number ISO/IEC DIS 10918-2. (The document number will change to IS 10918-2 when final approval is obtained.) A Part 3, covering extensions, is likely to appear in late 1994. The JPEG standard does not specify all details of an interchangeable file format. For the omitted details we follow the "JFIF" conventions, revision 1.02. A copy of the JFIF spec is available from: Literature Department C-Cube Microsystems, Inc. 1778 McCarthy Blvd. Milpitas, CA 95035 phone (408) 944-6300, fax (408) 944-6314 A PostScript version of this document is available at ftp.uu.net, file graphics/jpeg/jfif.ps.Z. It can also be obtained by e-mail from the C-Cube mail server, netlib@c3.pla.ca.us. Send the message "send jfif_ps from jpeg" to the server to obtain the JFIF document; send the message "help" if you have trouble. The TIFF 6.0 file format specification can be obtained by FTP from sgi.com (192.48.153.1), file graphics/tiff/TIFF6.ps.Z; or you can order a printed copy from Aldus Corp. at (206) 628-6593. It should be noted that the TIFF 6.0 spec of 3-June-92 has a number of serious problems in its JPEG features. A redesign effort is currently underway to correct these problems; it is expected to result in a new, incompatible, spec. IJG intends to support the corrected version of TIFF when the new spec is issued. ARCHIVE LOCATIONS ================= (This version is an alpha-test release and will not be publicly archived. The following paragraphs refer to the most recent official release. Future official releases will be archived in the same places, although file names will change to include the proper version number.) The "official" archive site for this software is ftp.uu.net (Internet address 192.48.96.9). The most recent released version can always be found there in directory graphics/jpeg. This particular version will be archived as graphics/jpeg/jpegsrc.v4.tar.Z. If you are on the Internet, you can retrieve files from UUNET by standard anonymous FTP. If you don't have FTP access, UUNET's archives are also available via UUCP; contact postmaster@uunet.uu.net for information on retrieving files that way. Numerous Internet sites maintain copies of the UUNET files; in particular, you can probably find a copy at any site that archives comp.sources.misc submissions. However, only ftp.uu.net is guaranteed to have the latest official version. You can also obtain this software from CompuServe, in the GRAPHSUPPORT forum (GO GRAPHSUP); this version will be file jpsrc4.zip in library 15. Again, CompuServe is not guaranteed to have the very latest version. The JPEG FAQ (Frequently Asked Questions) article is a useful source of general information about JPEG. It is updated constantly and therefore is not included in this distribution. The FAQ is posted every two weeks to Usenet newsgroups comp.graphics, news.answers, and other groups. You can always obtain the latest version from the news.answers archive at rtfm.mit.edu (18.70.0.209). By FTP, fetch /pub/usenet/news.answers/jpeg-faq. If you don't have FTP, send e-mail to mail-server@rtfm.mit.edu with body "send usenet/news.answers/jpeg-faq". RELATED SOFTWARE ================ Numerous viewing and image manipulation programs now support JPEG. (Quite a few of them use this library to do so.) The JPEG FAQ described above lists some of the more popular free and shareware viewers, and tells where to obtain them on Internet. If you are on a Unix machine, we highly recommend Jef Poskanzer's free PBMPLUS image software, which provides many useful operations on PPM-format image files. In particular, it can convert PPM images to and from a wide range of other formats. You can obtain this package by FTP from ftp.x.org (contrib/pbmplus*.tar.Z) or ftp.ee.lbl.gov (pbmplus*.tar.Z). There is also a newer update of this package called NETPBM, available from wuarchive.wustl.edu under directory /graphics/graphics/packages/NetPBM/. Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; you are likely to have difficulty making it work on any non-Unix machine. A different free JPEG implementation, written by the PVRG group at Stanford, is available from havefun.stanford.edu in directory pub/jpeg. This program is designed for research and experimentation rather than production use; it is slower, harder to use, and less portable than the IJG code, but it implements a larger subset of the JPEG standard. In particular, it supports lossless JPEG. FILE FORMAT WARS ================ Some JPEG programs produce files that are not compatible with our library. The root of the problem is that the ISO JPEG committee failed to specify a concrete file format. Some vendors "filled in the blanks" on their own, creating proprietary formats that no one else could read. (For example, none of the early commercial JPEG implementations for the Macintosh were able to exchange compressed files.) The file format we have adopted is called JFIF (see REFERENCES). This format has been agreed to by a number of major commercial JPEG vendors, and it has become the de facto standard. JFIF is a minimal or "low end" representation. Work is also going forward to incorporate JPEG compression into the TIFF standard, for use in "high end" applications that need to record a lot of additional data about an image. We intend to support TIFF in the future. We hope that these two formats will be sufficient and that other, incompatible JPEG file formats will not proliferate. Indeed, part of the reason for developing and releasing this free software is to help force rapid convergence to de facto standards for JPEG file formats. SUPPORT STANDARD, NON-PROPRIETARY FORMATS: demand JFIF or TIFF/JPEG! TO DO ===== Lots. This pre-release version is far from complete and no doubt has bugs in what it does implement. Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. \ No newline at end of file diff --git a/Independent JPEG Group/ansi2knr.1 b/Independent JPEG Group/ansi2knr.1 new file mode 100644 index 0000000..e7067d2 --- /dev/null +++ b/Independent JPEG Group/ansi2knr.1 @@ -0,0 +1 @@ +.TH ANSI2KNR 1 "31 December 1990" .SH NAME ansi2knr \- convert ANSI C to Kernighan & Ritchie C .SH SYNOPSIS .I ansi2knr input_file output_file .SH DESCRIPTION If no output_file is supplied, output goes to stdout. .br There are no error messages. .sp .I ansi2knr recognizes functions by seeing a non-keyword identifier at the left margin, followed by a left parenthesis, with a right parenthesis as the last character on the line. It will recognize a multi-line header if the last character on each line but the last is a left parenthesis or comma. These algorithms ignore whitespace and comments, except that the function name must be the first thing on the line. .sp The following constructs will confuse it: .br - Any other construct that starts at the left margin and follows the above syntax (such as a macro or function call). .br - Macros that tinker with the syntax of the function header. \ No newline at end of file diff --git a/Independent JPEG Group/ansi2knr.c b/Independent JPEG Group/ansi2knr.c new file mode 100644 index 0000000..e9d07b6 --- /dev/null +++ b/Independent JPEG Group/ansi2knr.c @@ -0,0 +1 @@ +/* Copyright (C) 1989, 1991, 1993 Aladdin Enterprises. All rights reserved. */ /* ansi2knr.c */ /* Convert ANSI function declarations to K&R syntax */ /* ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Refer to the GNU General Public License for full details. Everyone is granted permission to copy, modify and redistribute ansi2knr, but only under the conditions described in the GNU General Public License. A copy of this license is supposed to have been given to you along with ansi2knr so you can know your rights and responsibilities. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* ---------- Here is the GNU GPL file COPYING, referred to above ---------- ----- These terms do NOT apply to the JPEG software itself; see README ------ GHOSTSCRIPT GENERAL PUBLIC LICENSE (Clarified 11 Feb 1988) Copyright (C) 1988 Richard M. Stallman Everyone is permitted to copy and distribute verbatim copies of this license, but changing it is not allowed. You can also use this wording to make the terms for other programs. The license agreements of most software companies keep you at the mercy of those companies. By contrast, our general public license is intended to give everyone the right to share Ghostscript. To make sure that you get the rights we want you to have, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. Hence this license agreement. Specifically, we want to make sure that you have the right to give away copies of Ghostscript, that you receive source code or else can get it if you want it, that you can change Ghostscript or use pieces of it in new free programs, and that you know you can do these things. To make sure that everyone has such rights, we have to forbid you to deprive anyone else of these rights. For example, if you distribute copies of Ghostscript, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. Also, for our own protection, we must make certain that everyone finds out that there is no warranty for Ghostscript. If Ghostscript is modified by someone else and passed on, we want its recipients to know that what they have is not what we distributed, so that any problems introduced by others will not reflect on our reputation. Therefore we (Richard M. Stallman and the Free Software Foundation, Inc.) make the following terms which say what you must do to be allowed to distribute or change Ghostscript. COPYING POLICIES 1. You may copy and distribute verbatim copies of Ghostscript source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy a valid copyright and license notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved. Distributed by Free Software Foundation, Inc." (or with whatever year is appropriate); keep intact the notices on all files that refer to this License Agreement and to the absence of any warranty; and give any other recipients of the Ghostscript program a copy of this License Agreement along with the program. You may charge a distribution fee for the physical act of transferring a copy. 2. You may modify your copy or copies of Ghostscript or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: a) cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and b) cause the whole of any work that you distribute or publish, that in whole or in part contains or is a derivative of Ghostscript or any part thereof, to be licensed at no charge to all third parties on terms identical to those contained in this License Agreement (except that you may choose to grant more extensive warranty protection to some or all third parties, at your option). c) You may charge a distribution fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another unrelated program with this program (or its derivative) on a volume of a storage or distribution medium does not bring the other program under the scope of these terms. 3. You may copy and distribute Ghostscript (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: a) accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, b) accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal shipping charge) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, c) accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs. 4. You may not copy, sublicense, distribute or transfer Ghostscript except as expressly provided under this License Agreement. Any attempt otherwise to copy, sublicense, distribute or transfer Ghostscript is void and your rights to use the program under this License agreement shall be automatically terminated. However, parties who have received computer software programs from you with this License Agreement will not have their licenses terminated so long as such parties remain in full compliance. 5. If you wish to incorporate parts of Ghostscript into other free programs whose distribution conditions are different, write to the Free Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked out a simple rule that can be stated here, but we will often permit this. We will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software. Your comments and suggestions about our licensing policies and our software are welcome! Please contact the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296. NO WARRANTY BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. -------------------- End of file COPYING ------------------------------ */ #include #include #ifdef BSD #include #else #ifdef VMS extern int strlen(), strncmp(); #else #include #endif #endif /* malloc and free should be declared in stdlib.h, */ /* but if you've got a K&R compiler, they probably aren't. */ #ifdef MSDOS #include #else #ifdef VMS extern char *malloc(); extern void free(); #else extern char *malloc(); extern int free(); #endif #endif /* Usage: ansi2knr input_file [output_file] * If no output_file is supplied, output goes to stdout. * There are no error messages. * * ansi2knr recognizes functions by seeing a non-keyword identifier * at the left margin, followed by a left parenthesis, * with a right parenthesis as the last character on the line. * It will recognize a multi-line header provided that the last character * of the last line of the header is a right parenthesis, * and no intervening line ends with a left brace or a semicolon. * These algorithms ignore whitespace and comments, except that * the function name must be the first thing on the line. * The following constructs will confuse it: * - Any other construct that starts at the left margin and * follows the above syntax (such as a macro or function call). * - Macros that tinker with the syntax of the function header. */ /* Scanning macros */ #define isidchar(ch) (isalnum(ch) || (ch) == '_') #define isidfirstchar(ch) (isalpha(ch) || (ch) == '_') /* Forward references */ char *skipspace(); int writeblanks(); int test1(); int convert1(); /* The main program */ main(argc, argv) int argc; char *argv[]; { FILE *in, *out; #define bufsize 5000 /* arbitrary size */ char *buf; char *line; switch ( argc ) { default: printf("Usage: ansi2knr input_file [output_file]\n"); exit(0); case 2: out = stdout; break; case 3: out = fopen(argv[2], "w"); if ( out == NULL ) { fprintf(stderr, "Cannot open %s\n", argv[2]); exit(1); } } in = fopen(argv[1], "r"); if ( in == NULL ) { fprintf(stderr, "Cannot open %s\n", argv[1]); exit(1); } fprintf(out, "#line 1 \"%s\"\n", argv[1]); buf = malloc(bufsize); line = buf; while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL ) { switch ( test1(buf) ) { case 1: /* a function */ convert1(buf, out); break; case -1: /* maybe the start of a function */ line = buf + strlen(buf); if ( line != buf + (bufsize - 1) ) /* overflow check */ continue; /* falls through */ default: /* not a function */ fputs(buf, out); break; } line = buf; } if ( line != buf ) fputs(buf, out); free(buf); fclose(out); fclose(in); return 0; } /* Skip over space and comments, in either direction. */ char * skipspace(p, dir) register char *p; register int dir; /* 1 for forward, -1 for backward */ { for ( ; ; ) { while ( isspace(*p) ) p += dir; if ( !(*p == '/' && p[dir] == '*') ) break; p += dir; p += dir; while ( !(*p == '*' && p[dir] == '/') ) { if ( *p == 0 ) return p; /* multi-line comment?? */ p += dir; } p += dir; p += dir; } return p; } /* * Write blanks over part of a string. */ int writeblanks(start, end) char *start; char *end; { char *p; for ( p = start; p < end; p++ ) *p = ' '; return 0; } /* * Test whether the string in buf is a function definition. * The string may contain and/or end with a newline. * Return as follows: * 0 - definitely not a function definition; * 1 - definitely a function definition; * -1 - may be the beginning of a function definition, * append another line and look again. */ int test1(buf) char *buf; { register char *p = buf; char *bend; char *endfn; int contin; if ( !isidfirstchar(*p) ) return 0; /* no name at left margin */ bend = skipspace(buf + strlen(buf) - 1, -1); switch ( *bend ) { case ')': contin = 1; break; case '{': case ';': return 0; /* not a function */ default: contin = -1; } while ( isidchar(*p) ) p++; endfn = p; p = skipspace(p, 1); if ( *p++ != '(' ) return 0; /* not a function */ p = skipspace(p, 1); if ( *p == ')' ) return 0; /* no parameters */ /* Check that the apparent function name isn't a keyword. */ /* We only need to check for keywords that could be followed */ /* by a left parenthesis (which, unfortunately, is most of them). */ { static char *words[] = { "asm", "auto", "case", "char", "const", "double", "extern", "float", "for", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "switch", "typedef", "unsigned", "void", "volatile", "while", 0 }; char **key = words; char *kp; int len = endfn - buf; while ( (kp = *key) != 0 ) { if ( strlen(kp) == len && !strncmp(kp, buf, len) ) return 0; /* name is a keyword */ key++; } } return contin; } int convert1(buf, out) char *buf; FILE *out; { char *endfn; register char *p; char **breaks; unsigned num_breaks = 2; /* for testing */ char **btop; char **bp; char **ap; /* Pre-ANSI implementations don't agree on whether strchr */ /* is called strchr or index, so we open-code it here. */ for ( endfn = buf; *(endfn++) != '('; ) ; top: p = endfn; breaks = (char **)malloc(sizeof(char *) * num_breaks * 2); if ( breaks == 0 ) { /* Couldn't allocate break table, give up */ fprintf(stderr, "Unable to allocate break table!\n"); fputs(buf, out); return -1; } btop = breaks + num_breaks * 2 - 2; bp = breaks; /* Parse the argument list */ do { int level = 0; char *end = NULL; if ( bp >= btop ) { /* Filled up break table. */ /* Allocate a bigger one and start over. */ free((char *)breaks); num_breaks <<= 1; goto top; } *bp++ = p; /* Find the end of the argument */ for ( ; end == NULL; p++ ) { switch(*p) { case ',': if ( !level ) end = p; break; case '(': level++; break; case ')': if ( --level < 0 ) end = p; break; case '/': p = skipspace(p, 1) - 1; break; default: ; } } p--; /* back up over terminator */ /* Find the name being declared. */ /* This is complicated because of procedure and */ /* array modifiers. */ for ( ; ; ) { p = skipspace(p - 1, -1); switch ( *p ) { case ']': /* skip array dimension(s) */ case ')': /* skip procedure args OR name */ { int level = 1; while ( level ) switch ( *--p ) { case ']': case ')': level++; break; case '[': case '(': level--; break; case '/': p = skipspace(p, -1) + 1; break; default: ; } } if ( *p == '(' && *skipspace(p + 1, 1) == '*' ) { /* We found the name being declared */ while ( !isidfirstchar(*p) ) p = skipspace(p, 1) + 1; goto found; } break; default: goto found; } } found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' ) { p++; if ( bp == breaks + 1 ) /* sole argument */ writeblanks(breaks[0], p); else writeblanks(bp[-1] - 1, p); bp--; } else { while ( isidchar(*p) ) p--; *bp++ = p+1; } p = end; } while ( *p++ == ',' ); *bp = p; /* Make a special check for 'void' arglist */ if ( bp == breaks+2 ) { p = skipspace(breaks[0], 1); if ( !strncmp(p, "void", 4) ) { p = skipspace(p+4, 1); if ( p == breaks[2] - 1 ) { bp = breaks; /* yup, pretend arglist is empty */ writeblanks(breaks[0], p + 1); } } } /* Put out the function name */ p = buf; while ( p != endfn ) putc(*p, out), p++; /* Put out the declaration */ for ( ap = breaks+1; ap < bp; ap += 2 ) { p = *ap; while ( isidchar(*p) ) putc(*p, out), p++; if ( ap < bp - 1 ) fputs(", ", out); } fputs(") ", out); /* Put out the argument declarations */ for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';'; fputs(breaks[0], out); free((char *)breaks); return 0; } \ No newline at end of file diff --git a/Independent JPEG Group/cderror.h b/Independent JPEG Group/cderror.h new file mode 100644 index 0000000..b70e9cb --- /dev/null +++ b/Independent JPEG Group/cderror.h @@ -0,0 +1 @@ +/* * cderror.h * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the error and message codes for the cjpeg/djpeg * applications. These strings are not needed as part of the JPEG library * proper. * Edit this file to add new codes, or to translate the message strings to * some other language. */ /* To define the enum list of message codes, include this file without * defining JMAKE_MSG_TABLE. To create the message string table, include it * again with JMAKE_MSG_TABLE defined (this should be done in just one module). */ #ifdef JMAKE_MSG_TABLE const char * const addon_message_table[] = { #define JMESSAGE(code,string) string , #else /* not JMAKE_MSG_TABLE */ typedef enum { #define JMESSAGE(code,string) code , #endif /* JMAKE_MSG_TABLE */ JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ #ifdef GIF_SUPPORTED JMESSAGE(JERR_GIF_BUG, "GIF output got confused") JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") JMESSAGE(JERR_GIF_NOT, "Not a GIF file") JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") JMESSAGE(JTRC_GIF_BADVERSION, "Warning: unexpected GIF version number '%c%c%c'") JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") #endif /* GIF_SUPPORTED */ #ifdef PPM_SUPPORTED JMESSAGE(JERR_PPM_SAMPLESIZE, "PPM code requires 8-bit JSAMPLEs") JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") JMESSAGE(JERR_PPM_NOT, "Not a PPM file") JMESSAGE(JTRC_PGM, "%ux%u PGM image") JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") JMESSAGE(JTRC_PPM, "%ux%u PPM image") JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") #endif /* PPM_SUPPORTED */ #ifdef RLE_SUPPORTED JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") JMESSAGE(JERR_RLE_NOT, "Not an RLE file") JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") #endif /* RLE_SUPPORTED */ #ifdef TARGA_SUPPORTED JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") #else JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") #endif /* TARGA_SUPPORTED */ JMESSAGE(JERR_TOO_MANY_COLORS, "Output file format cannot handle %d colormap entries") JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") #ifdef TARGA_SUPPORTED JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format --- perhaps you need -targa") #else JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") #endif JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") #ifdef JMAKE_MSG_TABLE NULL }; #else /* not JMAKE_MSG_TABLE */ JMSG_LASTADDONCODE } ADDON_MESSAGE_CODE; #endif /* JMAKE_MSG_TABLE */ #undef JMESSAGE \ No newline at end of file diff --git a/Independent JPEG Group/cdjpeg.h b/Independent JPEG Group/cdjpeg.h new file mode 100644 index 0000000..567a486 --- /dev/null +++ b/Independent JPEG Group/cdjpeg.h @@ -0,0 +1 @@ +/* * cdjpeg.h * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains common declarations for the sample applications * cjpeg and djpeg. It is NOT used by the core JPEG library. */ #define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */ #define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* get library error codes too */ #include "cderror.h" /* get application-specific error codes */ /* * Object interface for cjpeg's source file decoding modules */ typedef struct cjpeg_source_struct * cjpeg_source_ptr; struct cjpeg_source_struct { JMETHOD(void, start_input, (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); JMETHOD(void, finish_input, (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); FILE *input_file; JSAMPARRAY buffer; JDIMENSION buffer_height; }; /* * Object interface for djpeg's output file encoding modules */ typedef struct djpeg_dest_struct * djpeg_dest_ptr; struct djpeg_dest_struct { /* start_output is called after jpeg_start_decompress finishes. * The color map will be ready at this time, if one is needed. */ JMETHOD(void, start_output, (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)); /* Emit the specified number of pixel rows from the buffer. */ JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied)); /* Finish up at the end of the image. */ JMETHOD(void, finish_output, (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)); /* Target file spec; filled in by djpeg.c after object is created. */ FILE * output_file; /* Output pixel-row buffer. Created by module init or start_output. * Width is cinfo->output_width * cinfo->output_components; * height is buffer_height. */ JSAMPARRAY buffer; JDIMENSION buffer_height; }; /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jinit_read_gif jIRdGIF #define jinit_write_gif jIWrGIF #define jinit_read_ppm jIRdPPM #define jinit_write_ppm jIWrPPM #define jinit_read_rle jIRdRLE #define jinit_write_rle jIWrRLE #define jinit_read_targa jIRdTarga #define jinit_write_targa jIWrTarga #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Module selection routines for I/O modules. */ EXTERN cjpeg_source_ptr jinit_read_gif JPP((j_compress_ptr cinfo)); EXTERN djpeg_dest_ptr jinit_write_gif JPP((j_decompress_ptr cinfo)); EXTERN cjpeg_source_ptr jinit_read_ppm JPP((j_compress_ptr cinfo)); EXTERN djpeg_dest_ptr jinit_write_ppm JPP((j_decompress_ptr cinfo)); EXTERN cjpeg_source_ptr jinit_read_rle JPP((j_compress_ptr cinfo)); EXTERN djpeg_dest_ptr jinit_write_rle JPP((j_decompress_ptr cinfo)); EXTERN cjpeg_source_ptr jinit_read_targa JPP((j_compress_ptr cinfo)); EXTERN djpeg_dest_ptr jinit_write_targa JPP((j_decompress_ptr cinfo)); \ No newline at end of file diff --git a/Independent JPEG Group/change.log b/Independent JPEG Group/change.log new file mode 100644 index 0000000..e3c7f77 --- /dev/null +++ b/Independent JPEG Group/change.log @@ -0,0 +1 @@ +CHANGE LOG for Independent JPEG Group's JPEG software Version 5alpha2 4-May-94 ------------------------- Two-pass color quantization is working, although it ought to be revisited to tune the algorithm for operation in RGB color space. The change to RGB means that the library can also quantize to an externally-supplied colormap; but I have not gotten around to implementing a djpeg switch for this. Output resizing via the IDCT works: see djpeg's "-scale" switch. The system design allows for more general rescaling at the upsample step, but I have no intention of implementing that anytime soon (any volunteers?). Other speed/quality tradeoff options remain to be implemented: alternate DCTs and merged color conversion/upsample/quantize are high on the list. Documentation is in fairly decent shape, although libjpeg.doc is still missing a few sections. All of the documentation will need updates as more features are added to v5. Version 5alpha1 6-Apr-94 ------------------------- This alpha-test release includes rewritten configuration/installation stuff. In particular there's now a "configure" script that should do everything needed for Unix installations. Please read install.doc. GIF and Targa file I/O are working again. Utah RLE is not there, and won't be unless someone volunteers to update those files. Huffman optimization and one-pass color quantization are working again. Two-pass quantization isn't fixed yet; ditto input smoothing and progress monitoring. Block smoothing is missing (and may remain so indefinitely...). Multiple-scan JPEG files are not supported for either encoding or decoding. None of the promised new v5 features (output resizing, speed/quality tradeoffs) are implemented yet. The documentation needs work; in particular, usage.doc/cjpeg.1/djpeg.1 have not been updated. I have plans for an extensive "libjpeg.doc" file describing use of the library, but haven't written anything yet. Changes from version 4 ---------------------- Version 5 represents a nearly complete redesign and rewrite of the IJG software. Major user-visible changes include: * Automatic configuration simplifies installation for most Unix systems. * A range of speed vs. image quality tradeoffs are [will be] supported. This includes resizing of an image during decompression: scaling down by a factor of 1/2, 1/4, or 1/8 is handled very efficiently. The application programmer's interface to the library has changed completely. Notable improvements include: * We have eliminated the use of callback routines for handling the uncompressed image data. The application now sees the library as a set of routines that it calls to read or write image data on a scanline-by-scanline basis. * The application image data is represented in a conventional interleaved- pixel format, rather than as a separate array for each color channel. This can save a copying step in many programs. * The handling of compressed data has been cleaned up: the application can supply routines to source or sink the compressed data. It is possible to suspend processing on source/sink buffer overrun, although this is not supported in all operating modes. * All static state has been eliminated from the library, so that multiple instances of compression or decompression can be active concurrently. * JPEG abbreviated datastream formats are supported, ie, quantization and Huffman tables can be stored separately from the image data. The last widely used release before the version 5 rewrite was version 4A of 18-Feb-93. Change logs before that point have been discarded, since they are not of much interest after the rewrite. \ No newline at end of file diff --git a/Independent JPEG Group/cjpeg.1 b/Independent JPEG Group/cjpeg.1 new file mode 100644 index 0000000..03bd346 --- /dev/null +++ b/Independent JPEG Group/cjpeg.1 @@ -0,0 +1 @@ +.TH CJPEG 1 "24 April 1994" .SH NAME cjpeg \- compress an image file to a JPEG file .SH SYNOPSIS .B cjpeg [ .BI \-quality " N" ] [ .B \-grayscale ] [ .B \-optimize ] [ .B \-targa ] [ .BI \-maxmemory " N" ] [ .BI \-restart " N" ] [ .BI \-smooth " N" ] [ .B \-verbose ] [ .B \-debug ] [ .B \-arithmetic ] [ .B \-baseline ] [ .B \-nointerleave ] [ .BI \-qtables " file" ] [ .BI \-qslots " N[,...]" ] [ .BI \-sample " HxV[,...]" ] [ .I filename ] .LP .SH DESCRIPTION .LP .B cjpeg compresses the named image file, or the standard input if no file is named, and produces a JPEG/JFIF file on the standard output. The currently supported input file formats are: PPM (PBMPLUS color format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit format). (RLE is supported only if the URT library is available.) .SH OPTIONS All switch names may be abbreviated; for example, .B \-grayscale may be written .B \-gray or .BR \-gr . Most of the "basic" switches can be abbreviated to as little as one letter. Upper and lower case are equivalent (thus .B \-GIF is the same as .BR \-gif ). British spellings are also accepted (e.g., .BR \-greyscale ), though for brevity these are not mentioned below. .PP The basic switches are: .TP .BI \-quality " N" Scale quantization tables to adjust image quality. Quality is 0 (worst) to 100 (best); default is 75. (See below for more info.) .TP .B \-grayscale Create monochrome JPEG file from color input. Be sure to use this switch when compressing a grayscale GIF file, because .B cjpeg isn't bright enough to notice whether a GIF file uses only shades of gray. By saying .BR \-grayscale , you'll get a smaller JPEG file that takes less time to process. .TP .B \-optimize Perform optimization of entropy encoding parameters. Without this, default encoding parameters are used. .B \-optimize usually makes the JPEG file a little smaller, but .B cjpeg runs somewhat slower and needs much more memory. Image quality and speed of decompression are unaffected by .BR \-optimize . .TP .B \-targa Input file is Targa format. Targa files that contain an "identification" field will not be automatically recognized by .BR cjpeg ; for such files you must specify .B \-targa to make .B cjpeg treat the input as Targa format. .PP The .B \-quality switch lets you trade off compressed file size against quality of the reconstructed image: the higher the quality setting, the larger the JPEG file, and the closer the output image will be to the original input. Normally you want to use the lowest quality setting (smallest file) that decompresses into something visually indistinguishable from the original image. For this purpose the quality setting should be between 50 and 95; the default of 75 is often about right. If you see defects at .B \-quality 75, then go up 5 or 10 counts at a time until you are happy with the output image. (The optimal setting will vary from one image to another.) .PP .B \-quality 100 will generate a quantization table of all 1's, eliminating loss in the quantization step (but there is still information loss in subsampling, as well as roundoff error). This setting is mainly of interest for experimental purposes. Quality values above about 95 are .B not recommended for normal use; the compressed file size goes up dramatically for hardly any gain in output image quality. .PP In the other direction, quality values below 50 will produce very small files of low image quality. Settings around 5 to 10 might be useful in preparing an index of a large image library, for example. Try .B \-quality 2 (or so) for some amusing Cubist effects. (Note: quality values below about 25 generate 2-byte quantization tables, which are considered optional in the JPEG standard. .B cjpeg emits a warning message when you give such a quality value, because some commercial JPEG programs may be unable to decode the resulting file. Use .B \-baseline if you need to ensure compatibility at low quality values.) .PP Switches for advanced users: .TP .BI \-maxmemory " N" Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, .B \-max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. .TP .BI \-restart " N" Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is attached to the number. .B \-restart 0 (the default) means no restart markers. .TP .BI \-smooth " N" Smooth the input image to eliminate dithering noise. N, ranging from 1 to 100, indicates the strength of smoothing. 0 (the default) means no smoothing. .TP .B \-verbose Enable debug printout. More .BR \-v 's give more output. Also, version information is printed at startup. .TP .B \-debug Same as .BR \-verbose . .PP The .B \-restart option inserts extra markers that allow a JPEG decoder to resynchronize after a transmission error. Without restart markers, any damage to a compressed file will usually ruin the image from the point of the error to the end of the image; with restart markers, the damage is usually confined to the portion of the image up to the next restart marker. Of course, the restart markers occupy extra space. We recommend .B \-restart 1 for images that will be transmitted across unreliable networks such as Usenet. .PP The .B \-smooth option filters the input to eliminate fine-scale noise. This is often useful when converting GIF files to JPEG: a moderate smoothing factor of 10 to 50 gets rid of dithering patterns in the input file, resulting in a smaller JPEG file and a better-looking image. Too large a smoothing factor will visibly blur the image, however. .PP Switches for wizards: .TP .B \-arithmetic Use arithmetic coding rather than Huffman coding. (Not currently supported for legal reasons.) .TP .B \-baseline Force a baseline JPEG file to be generated. This clamps quantization values to 8 bits even at low quality settings. .TP .B \-nointerleave Generate noninterleaved JPEG file (not yet supported). .TP .BI \-qtables " file" Use the quantization tables given in the specified file. The file should contain one to four tables (64 values each) as plain text. Comments preceded by '#' may be included in the file. The tables are implicitly numbered 0,1,etc. If .BI \-quality " N" is also specified, the values in the file are scaled according to .BR cjpeg 's quality scaling curve. .TP .BI \-qslots " N[,...]" Select which quantization table to use for each color component. By default, table 0 is used for luminance and table 1 for chrominance components. .TP .BI \-sample " HxV[,...]" Set JPEG sampling factors. If you specify fewer H/V pairs than there are components, the remaining components are set to 1x1 sampling. The default setting is equivalent to \fB\-sample 2x2\fR. .PP The "wizard" switches are intended for experimentation with JPEG. If you don't know what you are doing, \fBdon't use them\fR. You can easily produce files with worse image quality and/or poorer compression than you'll get from the default settings. Furthermore, these switches should not be used when making files intended for general use, because not all JPEG implementations will support unusual JPEG parameter settings. .SH EXAMPLES .LP This example compresses the PPM file foo.ppm with a quality factor of 60 and saves the output as foo.jpg: .IP .B cjpeg \-quality .I 60 foo.ppm .B > .I foo.jpg .SH HINTS Color GIF files are not the ideal input for JPEG; JPEG is really intended for compressing full-color (24-bit) images. In particular, don't try to convert cartoons, line drawings, and other images that have only a few distinct colors. GIF works great on these, JPEG does not. If you want to convert a GIF to JPEG, you should experiment with .BR cjpeg 's .B \-quality and .B \-smooth options to get a satisfactory conversion. .B \-smooth 10 or so is often helpful. .PP Avoid running an image through a series of JPEG compression/decompression cycles. Image quality loss will accumulate; after ten or so cycles the image may be noticeably worse than it was after one cycle. It's best to use a lossless format while manipulating an image, then convert to JPEG format when you are ready to file the image away. .PP The .B \-optimize option to .B cjpeg is worth using when you are making a "final" version for posting or archiving. It's also a win when you are using low quality settings to make very small JPEG files; the percentage improvement is often a lot more than it is on larger files. .SH ENVIRONMENT .TP .B JPEGMEM If this environment variable is set, its value is the default memory limit. The value is specified as described for the .B \-maxmemory switch. .B JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit .BR \-maxmemory . .SH SEE ALSO .BR djpeg (1) .br .BR ppm (5), .BR pgm (5) .br Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. .SH AUTHOR Independent JPEG Group .SH BUGS Arithmetic coding is not supported for legal reasons. .PP Not all variants of Targa file format are supported. .PP The .B \-targa switch is not a bug, it's a feature. (It would be a bug if the Targa format designers had not been clueless.) .PP Still not as fast as we'd like. \ No newline at end of file diff --git a/Independent JPEG Group/cjpeg.c b/Independent JPEG Group/cjpeg.c new file mode 100644 index 0000000..7e8a69d --- /dev/null +++ b/Independent JPEG Group/cjpeg.c @@ -0,0 +1 @@ +/* * cjpeg.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a command-line user interface for the JPEG compressor. * It should work on any system with Unix- or MS-DOS-style command lines. * * Two different command line styles are permitted, depending on the * compile-time switch TWO_FILE_COMMANDLINE: * cjpeg [options] inputfile outputfile * cjpeg [options] [inputfile] * In the second style, output is always to standard output, which you'd * normally redirect to a file or pipe to some other program. Input is * either from a named file or from standard input (typically redirected). * The second style is convenient on Unix but is unhelpful on systems that * don't support pipes. Also, you MUST use the first style if your system * doesn't do binary I/O to stdin/stdout. * To simplify script writing, the "-outfile" switch is provided. The syntax * cjpeg [options] -outfile outputfile inputfile * works regardless of which command line style is used. */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #define JMAKE_MSG_TABLE #include "cderror.h" /* create message string table */ #include "jversion.h" /* for version message */ #include /* to declare isupper(), tolower() */ #ifdef NEED_SIGNAL_CATCHER #include /* to declare signal() */ #endif #ifdef USE_SETMODE #include /* to declare setmode() */ #endif #ifdef THINK_C #include /* command-line reader for Macintosh */ #endif #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #define WRITE_BINARY "w" #else #define READ_BINARY "rb" #define WRITE_BINARY "wb" #endif #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif #ifndef EXIT_SUCCESS #ifdef VMS #define EXIT_SUCCESS 1 /* VMS is very nonstandard */ #else #define EXIT_SUCCESS 0 #endif #endif #ifndef EXIT_WARNING #ifdef VMS #define EXIT_WARNING 1 /* VMS is very nonstandard */ #else #define EXIT_WARNING 2 #endif #endif /* * This routine determines what format the input file is, * and selects the appropriate input-reading module. * * To determine which family of input formats the file belongs to, * we may look only at the first byte of the file, since C does not * guarantee that more than one character can be pushed back with ungetc. * Looking at additional bytes would require one of these approaches: * 1) assume we can fseek() the input file (fails for piped input); * 2) assume we can push back more than one character (works in * some C implementations, but unportable); * 3) provide our own buffering (breaks input readers that want to use * stdio directly, such as the RLE library); * or 4) don't put back the data, and modify the input_init methods to assume * they start reading after the start of file (also breaks RLE library). * #1 is attractive for MS-DOS but is untenable on Unix. * * The most portable solution for file types that can't be identified by their * first byte is to make the user tell us what they are. This is also the * only approach for "raw" file types that contain only arbitrary values. * We presently apply this method for Targa files. Most of the time Targa * files start with 0x00, so we recognize that case. Potentially, however, * a Targa file could start with any byte value (byte 0 is the length of the * seldom-used ID field), so we provide a switch to force Targa input mode. */ static boolean is_targa; /* records user -targa switch */ LOCAL cjpeg_source_ptr select_file_type (j_compress_ptr cinfo, FILE * infile) { int c; if (is_targa) { #ifdef TARGA_SUPPORTED return jinit_read_targa(cinfo); #else ERREXIT(cinfo, JERR_TGA_NOTCOMP); #endif } if ((c = getc(infile)) == EOF) ERREXIT(cinfo, JERR_INPUT_EMPTY); if (ungetc(c, infile) == EOF) ERREXIT(cinfo, JERR_UNGETC_FAILED); switch (c) { #ifdef GIF_SUPPORTED case 'G': return jinit_read_gif(cinfo); #endif #ifdef PPM_SUPPORTED case 'P': return jinit_read_ppm(cinfo); #endif #ifdef RLE_SUPPORTED case 'R': return jinit_read_rle(cinfo); #endif #ifdef TARGA_SUPPORTED case 0x00: return jinit_read_targa(cinfo); #endif default: ERREXIT(cinfo, JERR_UNKNOWN_FORMAT); break; } return NULL; /* suppress compiler warnings */ } /* * Signal catcher to ensure that temporary files are removed before aborting. * NB: for Amiga Manx C this is actually a global routine named _abort(); * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus... */ #ifdef NEED_SIGNAL_CATCHER static j_common_ptr sig_cinfo; GLOBAL void signal_catcher (int signum) { if (sig_cinfo != NULL) { if (sig_cinfo->err != NULL) /* turn off trace output */ sig_cinfo->err->trace_level = 0; jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */ } exit(EXIT_FAILURE); } #endif /* * Argument-parsing code. * The switch parser is designed to be useful with DOS-style command line * syntax, ie, intermixed switches and file names, where only the switches * to the left of a given file name affect processing of that file. * The main program in this file doesn't actually use this capability... */ static char * progname; /* program name for error messages */ static char * outfilename; /* for -outfile switch */ LOCAL void usage (void) /* complain about bad command line */ { fprintf(stderr, "usage: %s [switches] ", progname); #ifdef TWO_FILE_COMMANDLINE fprintf(stderr, "inputfile outputfile\n"); #else fprintf(stderr, "[inputfile]\n"); #endif fprintf(stderr, "Switches (names may be abbreviated):\n"); fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n"); fprintf(stderr, " -grayscale Create monochrome JPEG file\n"); #ifdef ENTROPY_OPT_SUPPORTED fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n"); #endif #ifdef TARGA_SUPPORTED fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n"); #endif fprintf(stderr, "Switches for advanced users:\n"); fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n"); #ifdef INPUT_SMOOTHING_SUPPORTED fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n"); #endif fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); fprintf(stderr, "Switches for wizards:\n"); #ifdef C_ARITH_CODING_SUPPORTED fprintf(stderr, " -arithmetic Use arithmetic coding\n"); #endif fprintf(stderr, " -baseline Force baseline output\n"); #ifdef C_MULTISCAN_FILES_SUPPORTED fprintf(stderr, " -nointerleave Create noninterleaved JPEG file\n"); #endif fprintf(stderr, " -qtables file Use quantization tables given in file\n"); fprintf(stderr, " -qslots N[,...] Set component quantization tables\n"); fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n"); exit(EXIT_FAILURE); } LOCAL boolean keymatch (char * arg, const char * keyword, int minchars) /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ /* keyword is the constant keyword (must be lower case already), */ /* minchars is length of minimum legal abbreviation. */ { register int ca, ck; register int nmatched = 0; while ((ca = *arg++) != '\0') { if ((ck = *keyword++) == '\0') return FALSE; /* arg longer than keyword, no good */ if (isupper(ca)) /* force arg to lcase (assume ck is already) */ ca = tolower(ca); if (ca != ck) return FALSE; /* no good */ nmatched++; /* count matched characters */ } /* reached end of argument; fail if it's too short for unique abbrev */ if (nmatched < minchars) return FALSE; return TRUE; /* A-OK */ } LOCAL int qt_getc (FILE * file) /* Read next char, skipping over any comments (# to end of line) */ /* A comment/newline sequence is returned as a newline */ { register int ch; ch = getc(file); if (ch == '#') { do { ch = getc(file); } while (ch != '\n' && ch != EOF); } return ch; } LOCAL long read_qt_integer (FILE * file) /* Read an unsigned decimal integer from a quantization-table file */ /* Swallows one trailing character after the integer */ { register int ch; register long val; /* Skip any leading whitespace, detect EOF */ do { ch = qt_getc(file); if (ch == EOF) return EOF; } while (isspace(ch)); if (! isdigit(ch)) { fprintf(stderr, "%s: bogus data in quantization file\n", progname); exit(EXIT_FAILURE); } val = ch - '0'; while (ch = qt_getc(file), isdigit(ch)) { val *= 10; val += ch - '0'; } return val; } LOCAL void read_quant_tables (j_compress_ptr cinfo, char * filename, int scale_factor, boolean force_baseline) /* Read a set of quantization tables from the specified file. * The file is plain ASCII text: decimal numbers with whitespace between. * Comments preceded by '#' may be included in the file. * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values. * The tables are implicitly numbered 0,1,etc. * NOTE: does not affect the qslots mapping, which will default to selecting * table 0 for luminance (or primary) components, 1 for chrominance components. * You must use -qslots if you want a different component->table mapping. */ { /* ZIG[i] is the zigzag-order position of the i'th element of a DCT block */ /* read in natural order (left to right, top to bottom). */ static const int ZIG[DCTSIZE2] = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 }; FILE * fp; int tblno, i; long val; unsigned int table[DCTSIZE2]; if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, filename); exit(EXIT_FAILURE); } tblno = 0; while ((val = read_qt_integer(fp)) != EOF) { /* read 1st element of table */ if (tblno >= NUM_QUANT_TBLS) { fprintf(stderr, "%s: too many tables in file %s\n", progname, filename); exit(EXIT_FAILURE); } table[0] = (unsigned int) val; for (i = 1; i < DCTSIZE2; i++) { if ((val = read_qt_integer(fp)) == EOF) { fprintf(stderr, "%s: incomplete table in file %s\n", progname, filename); exit(EXIT_FAILURE); } table[ZIG[i]] = (unsigned int) val; } jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline); tblno++; } fclose(fp); } LOCAL void set_quant_slots (j_compress_ptr cinfo, char *arg) /* Process a quantization-table-selectors parameter string, of the form * N[,N,...] * If there are more components than parameters, the last value is replicated. */ { int val = 0; /* default table # */ int ci; char ch; for (ci = 0; ci < MAX_COMPONENTS; ci++) { if (*arg) { ch = ','; /* if not set by sscanf, will be ',' */ if (sscanf(arg, "%d%c", &val, &ch) < 1) usage(); if (ch != ',') usage(); /* syntax check */ if (val < 0 || val >= NUM_QUANT_TBLS) { fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n", NUM_QUANT_TBLS-1); exit(EXIT_FAILURE); } cinfo->comp_info[ci].quant_tbl_no = val; while (*arg && *arg++ != ',') /* advance to next segment of arg string */ ; } else { /* reached end of parameter, set remaining components to last table */ cinfo->comp_info[ci].quant_tbl_no = val; } } } LOCAL void set_sample_factors (j_compress_ptr cinfo, char *arg) /* Process a sample-factors parameter string, of the form * HxV[,HxV,...] * If there are more components than parameters, "1x1" is assumed. */ { int ci, val1, val2; char ch1, ch2; for (ci = 0; ci < MAX_COMPONENTS; ci++) { if (*arg) { ch2 = ','; /* if not set by sscanf, will be ',' */ if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3) usage(); if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') usage(); /* syntax check */ if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) { fprintf(stderr, "JPEG sampling factors must be 1..4\n"); exit(EXIT_FAILURE); } cinfo->comp_info[ci].h_samp_factor = val1; cinfo->comp_info[ci].v_samp_factor = val2; while (*arg && *arg++ != ',') /* advance to next segment of arg string */ ; } else { /* reached end of parameter, set remaining components to 1x1 sampling */ cinfo->comp_info[ci].h_samp_factor = 1; cinfo->comp_info[ci].v_samp_factor = 1; } } } LOCAL int parse_switches (j_compress_ptr cinfo, int last_file_arg_seen, int argc, char **argv) /* Initialize cinfo with default switch settings, then parse option switches. * Returns argv[] index of first file-name argument (== argc if none). * Any file names with indexes <= last_file_arg_seen are ignored; * they have presumably been processed in a previous iteration. * (Pass 0 for last_file_arg_seen on the first or only iteration.) */ { int argn; char * arg; int quality = 75; /* -quality parameter */ boolean force_baseline = FALSE; /* by default, allow 16-bit quantizers */ char * qtablefile = NULL; /* saves -qtables filename if any */ int q_scale_factor = 100; /* default to no scaling for -qtables */ char * qslotsarg = NULL; /* saves -qslots parm if any */ char * samplearg = NULL; /* saves -sample parm if any */ /* Set up default JPEG parameters. */ /* Note that default -quality level here need not, and does not, * match the default scaling for an explicit -qtables argument. */ jpeg_set_defaults(cinfo); /* note: default quality level = 75 */ is_targa = FALSE; outfilename = NULL; cinfo->err->trace_level = 0; /* Scan command line options, adjust parameters */ for (argn = 1; argn < argc; argn++) { arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ if (argn <= last_file_arg_seen) { outfilename = NULL; /* -outfile applies to just one input file */ continue; /* ignore this name if previously processed */ } break; /* else done parsing switches */ } arg++; /* advance past switch marker character */ if (keymatch(arg, "arithmetic", 1)) { /* Use arithmetic coding. */ #ifdef C_ARITH_CODING_SUPPORTED cinfo->arith_code = TRUE; #else fprintf(stderr, "%s: sorry, arithmetic coding not supported\n", progname); exit(EXIT_FAILURE); #endif } else if (keymatch(arg, "baseline", 1)) { /* Force baseline output (8-bit quantizer values). */ force_baseline = TRUE; /* Set quant tables (will be overridden if -qtables also given). */ jpeg_set_quality(cinfo, quality, force_baseline); } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { /* Enable debug printouts. */ /* On first -d, print version identification */ static boolean printed_version = FALSE; if (! printed_version) { fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n", JVERSION, JCOPYRIGHT); printed_version = TRUE; } cinfo->err->trace_level++; } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { /* Force a monochrome JPEG file to be generated. */ jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); } else if (keymatch(arg, "maxmemory", 1)) { /* Maximum memory in Kb (or Mb with 'm'). */ long lval; char ch = 'x'; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) usage(); if (ch == 'm' || ch == 'M') lval *= 1000L; cinfo->mem->max_memory_to_use = lval * 1000L; } else if (keymatch(arg, "nointerleave", 3)) { /* Create noninterleaved file. */ #ifdef C_MULTISCAN_FILES_SUPPORTED cinfo->interleave = FALSE; #else fprintf(stderr, "%s: sorry, multiple-scan support was not compiled\n", progname); exit(EXIT_FAILURE); #endif } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) { /* Enable entropy parm optimization. */ #ifdef ENTROPY_OPT_SUPPORTED cinfo->optimize_coding = TRUE; #else fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n", progname); exit(EXIT_FAILURE); #endif } else if (keymatch(arg, "outfile", 3)) { /* Set output file name. */ if (++argn >= argc) /* advance to next argument */ usage(); outfilename = argv[argn]; /* save it away for later use */ } else if (keymatch(arg, "quality", 1)) { /* Quality factor (quantization table scaling factor). */ if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d", &quality) != 1) usage(); /* Set quant tables (will be overridden if -qtables also given). */ jpeg_set_quality(cinfo, quality, force_baseline); /* Change scale factor in case -qtables is present. */ q_scale_factor = jpeg_quality_scaling(quality); } else if (keymatch(arg, "qslots", 2)) { /* Quantization table slot numbers. */ if (++argn >= argc) /* advance to next argument */ usage(); qslotsarg = argv[argn]; /* Must delay setting qslots until after we have processed any * colorspace-determining switches, since jpeg_set_colorspace sets * default quant table numbers. */ } else if (keymatch(arg, "qtables", 2)) { /* Quantization tables fetched from file. */ if (++argn >= argc) /* advance to next argument */ usage(); qtablefile = argv[argn]; /* We postpone actually reading the file in case -quality comes later. */ } else if (keymatch(arg, "restart", 1)) { /* Restart interval in MCU rows (or in MCUs with 'b'). */ long lval; char ch = 'x'; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) usage(); if (lval < 0 || lval > 65535L) usage(); if (ch == 'b' || ch == 'B') cinfo->restart_interval = (unsigned int) lval; else cinfo->restart_in_rows = (int) lval; } else if (keymatch(arg, "sample", 2)) { /* Set sampling factors. */ if (++argn >= argc) /* advance to next argument */ usage(); samplearg = argv[argn]; /* Must delay setting sample factors until after we have processed any * colorspace-determining switches, since jpeg_set_colorspace sets * default sampling factors. */ } else if (keymatch(arg, "smooth", 2)) { /* Set input smoothing factor. */ int val; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d", &val) != 1) usage(); if (val < 0 || val > 100) usage(); cinfo->smoothing_factor = val; } else if (keymatch(arg, "targa", 1)) { /* Input file is Targa format. */ is_targa = TRUE; } else { usage(); /* bogus switch */ } } /* Post-switch-scanning cleanup */ if (qtablefile != NULL) /* process -qtables if it was present */ read_quant_tables(cinfo, qtablefile, q_scale_factor, force_baseline); if (qslotsarg != NULL) /* process -qslots if it was present */ set_quant_slots(cinfo, qslotsarg); if (samplearg != NULL) /* process -sample if it was present */ set_sample_factors(cinfo, samplearg); return argn; /* return index of next arg (file name) */ } /* * The main program. */ GLOBAL int main (int argc, char **argv) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; int file_index; cjpeg_source_ptr src_mgr; FILE * input_file; FILE * output_file; JDIMENSION num_scanlines; /* On Mac, fetch a command line. */ #ifdef THINK_C argc = ccommand(&argv); #endif progname = argv[0]; /* Initialize the JPEG compression object with default error handling. */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); /* Add some application-specific error messages (from cderror.h) */ jerr.addon_message_table = addon_message_table; jerr.first_addon_message = JMSG_FIRSTADDONCODE; jerr.last_addon_message = JMSG_LASTADDONCODE; /* Now safe to enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER sig_cinfo = (j_common_ptr) &cinfo; signal(SIGINT, signal_catcher); #ifdef SIGTERM /* not all systems have SIGTERM */ signal(SIGTERM, signal_catcher); #endif #endif /* Scan command line to find file names. */ /* It is convenient to use just one switch-parsing routine, but the switch * values read here are ignored; we will rescan the switches after opening * the input file. */ cinfo.in_color_space = JCS_RGB; /* allow first jpeg_set_defaults() to work */ file_index = parse_switches(&cinfo, 0, argc, argv); #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { if (file_index != argc-2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } outfilename = argv[file_index+1]; } else { if (file_index != argc-1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } } #else /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } #endif /* TWO_FILE_COMMANDLINE */ /* Open the input file. */ if (file_index < argc) { if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdin), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdin\n", progname); exit(EXIT_FAILURE); } #else input_file = stdin; #endif } /* Open the output file. */ if (outfilename != NULL) { if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* default output file is stdout */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdout), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdout\n", progname); exit(EXIT_FAILURE); } #else output_file = stdout; #endif } #ifdef PROGRESS_REPORT /* Enable progress display, unless trace output is on */ if (jerr.trace_level == 0) c_methods.progress_monitor = progress_monitor; #endif /* Figure out the input file format, and set up to read it. */ src_mgr = select_file_type(&cinfo, input_file); src_mgr->input_file = input_file; /* Read the input file header to obtain file size & colorspace. */ (*src_mgr->start_input) (&cinfo, src_mgr); /* Adjust default compression parameters by re-parsing the options */ file_index = parse_switches(&cinfo, 0, argc, argv); /* Specify data destination for compression */ jpeg_stdio_dest(&cinfo, output_file); /* Start compressor */ jpeg_start_compress(&cinfo, TRUE); /* Process data */ while (cinfo.next_scanline < cinfo.image_height) { num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr); (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines); } /* Finish compression and release memory */ (*src_mgr->finish_input) (&cinfo, src_mgr); jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); #ifdef PROGRESS_REPORT /* Clear away progress display */ if (jerr.trace_level == 0) { fprintf(stderr, "\r \r"); fflush(stderr); } #endif /* All done. */ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ } \ No newline at end of file diff --git a/Independent JPEG Group/ckconfig.c b/Independent JPEG Group/ckconfig.c new file mode 100644 index 0000000..18d32e4 --- /dev/null +++ b/Independent JPEG Group/ckconfig.c @@ -0,0 +1 @@ +/* * ckconfig.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. */ /* * This program is intended to help you determine how to configure the JPEG * software for installation on a particular system. The idea is to try to * compile and execute this program. If your compiler fails to compile the * program, make changes as indicated in the comments below. Once you can * compile the program, run it, and it will produce a "jconfig.h" file for * your system. * * As a general rule, each time you try to compile this program, * pay attention only to the *first* error message you get from the compiler. * Many C compilers will issue lots of spurious error messages once they * have gotten confused. Go to the line indicated in the first error message, * and read the comments preceding that line to see what to change. * * Almost all of the edits you may need to make to this program consist of * changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL", * or vice versa. This is called defining or undefining that symbol. */ /* First we must see if your system has the include files we need. * We start out with the assumption that your system has all the ANSI-standard * include files. If you get any error trying to include one of these files, * undefine the corresponding HAVE_xxx symbol. */ #define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */ #ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */ #include #endif #define HAVE_STDLIB_H /* same thing for stdlib.h */ #ifdef HAVE_STDLIB_H #include #endif #include /* If you ain't got this, you ain't got C. */ /* We have to see if your string functions are defined by * strings.h (old BSD convention) or string.h (everybody else). * We try the non-BSD convention first; define NEED_BSD_STRINGS * if the compiler says it can't find string.h. */ #undef NEED_BSD_STRINGS #ifdef NEED_BSD_STRINGS #include #else #include #endif /* On some systems (especially older Unix machines), type size_t is * defined only in the include file . If you get a failure * on the size_t test below, try defining NEED_SYS_TYPES_H. */ #undef NEED_SYS_TYPES_H /* start by assuming we don't need it */ #ifdef NEED_SYS_TYPES_H #include #endif /* Usually type size_t is defined in one of the include files we've included * above. If not, you'll get an error on the "typedef size_t my_size_t;" line. * In that case, first try defining NEED_SYS_TYPES_H just above. * If that doesn't work, you'll have to search through your system library * to figure out which include file defines "size_t". Look for a line that * says "typedef something-or-other size_t;". Then, change the line below * that says "#include " to instead include the file * you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find * type size_t anywhere, try replacing "#include " with * "typedef unsigned int size_t;". */ #undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */ #ifdef NEED_SPECIAL_INCLUDE #include #endif typedef size_t my_size_t; /* The payoff: do we have size_t now? */ /* The next question is whether your compiler supports ANSI-style function * prototypes. You need to know this in order to choose between using * makefile.ansi and using makefile.unix. * The #define line below is set to assume you have ANSI function prototypes. * If you get an error in this group of lines, undefine HAVE_PROTOTYPES. */ #define HAVE_PROTOTYPES #ifdef HAVE_PROTOTYPES int testfunction (int arg1, int * arg2); /* check prototypes */ struct methods_struct { /* check method-pointer declarations */ int (*error_exit) (char *msgtext); int (*trace_message) (char *msgtext); int (*another_method) (void); }; int testfunction (int arg1, int * arg2) /* check definitions */ { return arg2[arg1]; } int test2function (void) /* check void arg list */ { return 0; } #endif /* Now we want to find out if your compiler knows what "unsigned char" means. * If you get an error on the "unsigned char un_char;" line, * then undefine HAVE_UNSIGNED_CHAR. */ #define HAVE_UNSIGNED_CHAR #ifdef HAVE_UNSIGNED_CHAR unsigned char un_char; #endif /* Now we want to find out if your compiler knows what "unsigned short" means. * If you get an error on the "unsigned short un_short;" line, * then undefine HAVE_UNSIGNED_SHORT. */ #define HAVE_UNSIGNED_SHORT #ifdef HAVE_UNSIGNED_SHORT unsigned short un_short; #endif /* Now we want to find out if your compiler understands type "void". * If you get an error anywhere in here, undefine HAVE_VOID. */ #define HAVE_VOID #ifdef HAVE_VOID typedef void * void_ptr; /* check void * */ typedef void (*void_func) (); /* check ptr to function returning void */ void test3function (arg1, arg2) /* check void function result */ void_ptr arg1; void_func arg2; { char * locptr = (char *) arg1; /* check casting to and from void * */ arg1 = (void *) locptr; (*arg2) (1, 2); /* check call of fcn returning void */ } #endif /* Now we want to find out if your compiler knows what "const" means. * If you get an error here, undefine HAVE_CONST. */ #define HAVE_CONST #ifdef HAVE_CONST static const int carray[3] = {1, 2, 3}; int test4function (arg1) const int arg1; { return carray[arg1]; } #endif /* If you get an error or warning about this structure definition, * define INCOMPLETE_TYPES_BROKEN. */ #undef INCOMPLETE_TYPES_BROKEN #ifndef INCOMPLETE_TYPES_BROKEN typedef struct undefined_structure * undef_struct_ptr; #endif /* If you get an error about duplicate names, * define NEED_SHORT_EXTERNAL_NAMES. */ #undef NEED_SHORT_EXTERNAL_NAMES #ifndef NEED_SHORT_EXTERNAL_NAMES int possibly_duplicate_function () { return 0; } int possibly_dupli_function () { return 1; } #endif /************************************************************************ * OK, that's it. You should not have to change anything beyond this * point in order to compile and execute this program. (You might get * some warnings, but you can ignore them.) * When you run the program, it will make a couple more tests that it * can do automatically, and then it will create jconfig.h and print out * any additional suggestions it has. ************************************************************************ */ int is_char_signed (arg) int arg; { if (arg == 189) { /* expected result for unsigned char */ return 0; /* type char is unsigned */ } else if (arg != -67) { /* expected result for signed char */ printf("Hmm, it seems 'char' is less than eight bits wide on your machine.\n"); printf("I fear the JPEG software will not work at all.\n\n"); } return 1; /* assume char is signed otherwise */ } int is_shifting_signed (arg) long arg; /* See whether right-shift on a long is signed or not. */ { long res = arg >> 4; if (res == 0x80817F4L) { /* expected result for unsigned */ return 0; /* right shift is unsigned */ } else if (res != -0x7F7E80CL) { /* expected result for signed */ printf("Right shift isn't acting as I expect it to.\n"); printf("I fear the JPEG software will not work at all.\n\n"); } return 1; /* right shift is signed */ } int main (argc, argv) int argc; char ** argv; { char signed_char_check = (char) (-67); FILE *outfile; /* Attempt to write jconfig.h */ if ((outfile = fopen("jconfig.h", "w")) == NULL) { printf("Failed to write jconfig.h\n"); return 1; } /* Write out all the info */ fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n"); fprintf(outfile, "/* see jconfig.doc for explanations */\n\n"); #ifdef HAVE_PROTOTYPES fprintf(outfile, "#define HAVE_PROTOTYPES\n"); #else fprintf(outfile, "#undef HAVE_PROTOTYPES\n"); #endif #ifdef HAVE_UNSIGNED_CHAR fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n"); #else fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n"); #endif #ifdef HAVE_UNSIGNED_SHORT fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n"); #else fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n"); #endif #ifdef HAVE_VOID fprintf(outfile, "/* #define void char */\n"); #else fprintf(outfile, "#define void char\n"); #endif #ifdef HAVE_CONST fprintf(outfile, "/* #define const */\n"); #else fprintf(outfile, "#define const\n"); #endif if (is_char_signed((int) signed_char_check)) fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n"); else fprintf(outfile, "#define CHAR_IS_UNSIGNED\n"); #ifdef HAVE_STDDEF_H fprintf(outfile, "#define HAVE_STDDEF_H\n"); #else fprintf(outfile, "#undef HAVE_STDDEF_H\n"); #endif #ifdef HAVE_STDLIB_H fprintf(outfile, "#define HAVE_STDLIB_H\n"); #else fprintf(outfile, "#undef HAVE_STDLIB_H\n"); #endif #ifdef NEED_BSD_STRINGS fprintf(outfile, "#define NEED_BSD_STRINGS\n"); #else fprintf(outfile, "#undef NEED_BSD_STRINGS\n"); #endif #ifdef NEED_SYS_TYPES_H fprintf(outfile, "#define NEED_SYS_TYPES_H\n"); #else fprintf(outfile, "#undef NEED_SYS_TYPES_H\n"); #endif fprintf(outfile, "#undef NEED_FAR_POINTERS\n"); #ifdef NEED_SHORT_EXTERNAL_NAMES fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n"); #else fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n"); #endif #ifdef INCOMPLETE_TYPES_BROKEN fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n"); #else fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n"); #endif fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n"); if (is_shifting_signed(-0x7F7E80B1L)) fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n"); else fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n"); fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n"); fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n"); fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n"); fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n"); fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n"); fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n"); fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n"); fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n"); fprintf(outfile, "#undef DONT_USE_B_MODE\n"); fprintf(outfile, "#undef PROGRESS_REPORT /* optional */\n"); fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n"); /* Close the jconfig.h file */ fclose(outfile); /* User report */ printf("Configuration check for Independent JPEG Group's software done.\n"); printf("\nI have written the jconfig.h file for you.\n\n"); #ifdef HAVE_PROTOTYPES printf("You should use makefile.ansi as the starting point for your Makefile.\n"); #else printf("You should use makefile.unix as the starting point for your Makefile.\n"); #endif #ifdef NEED_SPECIAL_INCLUDE printf("\nYou'll need to change jconfig.h to include the system include file\n"); printf("that you found type size_t in, or add a direct definition of type\n"); printf("size_t if that's what you used. Just add it to the end.\n"); #endif return 0; } \ No newline at end of file diff --git a/Independent JPEG Group/coderules.doc b/Independent JPEG Group/coderules.doc new file mode 100644 index 0000000..7e521bd --- /dev/null +++ b/Independent JPEG Group/coderules.doc @@ -0,0 +1 @@ +IJG JPEG LIBRARY: CODING RULES Copyright (C) 1991-1994, Thomas G. Lane. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. Since numerous people will be contributing code and bug fixes, it's important to establish a common coding style. The goal of using similar coding styles is much more important than the details of just what that style is. In general we follow the recommendations of "Recommended C Style and Coding Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and Brader). This document is available in the IJG FTP archive (see jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl). Block comments should be laid out thusly: /* * Block comments in this style. */ We indent statements in K&R style, e.g., if (test) { then-part; } else { else-part; } with two spaces per indentation level. (This indentation convention is handled automatically by GNU Emacs and many other text editors.) Multi-word names should be written in lower case with underscores, e.g., multi_word_name (not multiWordName). Preprocessor symbols and enum constants are similar but upper case (MULTI_WORD_NAME). Names should be unique within the first fifteen characters. (On some older systems, global names must be unique within six characters. We accommodate this without cluttering the source code by using macros to substitute shorter names.) We use function prototypes everywhere; we rely on automatic source code transformation to feed prototype-less C compilers. Transformation is done by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript). ansi2knr is not very bright, so it imposes a format requirement on function declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions should be written in the following style: LOCAL int * function_name (int a, char *b) { code... } Note that each function definition is prefixed with GLOBAL, LOCAL, or METHODDEF. These macros expand to "static" or nothing as appropriate. They provide a readable indication of the routine's usage and can readily be changed for special needs. (For instance, all routines can be made global for use with debuggers or code profilers that require it.) ansi2knr does not transform method declarations (function pointers in structs). We handle these with a macro JMETHOD, defined as #ifdef HAVE_PROTOTYPES #define JMETHOD(type,methodname,arglist) type (*methodname) arglist #else #define JMETHOD(type,methodname,arglist) type (*methodname) () #endif which is used like this: struct function_pointers { JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp)); JMETHOD(void, term_entropy_encoder, (void)); }; Note the set of parentheses surrounding the parameter list. A similar solution is used for external function declarations (see the JPP macro). If the code is to work on non-ANSI compilers, we cannot rely on a prototype declaration to coerce actual parameters into the right types. Therefore, use explicit casts on actual parameters whenever the actual parameter type is not identical to the formal parameter. Beware of implicit conversions to "int". It seems there are some non-ANSI compilers in which the sizeof() operator is defined to return int, yet size_t is defined as long. Needless to say, this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(), so that the result is guaranteed to be of type size_t. The JPEG library is intended to be used within larger programs. Furthermore, we want it to be reentrant so that it can be used by applications that process multiple images concurrently. The following rules support these requirements: 1. Avoid direct use of file I/O, "malloc", error report printouts, etc; pass these through the common routines provided. 2. Minimize global namespace pollution. Functions should be declared static wherever possible. (Note that our method-based calling conventions help this a lot: in many modules only the initialization function will ever need to be called directly, so only that function need be externally visible.) All global function names should begin with "jpeg_", and should have an abbreviated name (unique in the first six characters) substituted by macro when NEED_SHORT_EXTERNAL_NAMES is set. 3. Don't use global variables; anything that must be used in another module should be in the common data structures. 4. Don't use static variables except for read-only constant tables. Variables that should be private to a module can be placed into private structures (see the system architecture document, structure.doc). 5. Source file names should begin with "j" for files that are part of the library proper; source files that are not part of the library, such as cjpeg.c and djpeg.c, do not begin with "j". Keep source file names to eight characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep compression and decompression code in separate source files --- some applications may want only one half of the library. Note: these rules (particularly #4) are not followed religiously in the modules that are used in cjpeg/djpeg but are not part of the JPEG library proper. Those modules are not really intended to be used in other applications. \ No newline at end of file diff --git a/Independent JPEG Group/configure_.TXT b/Independent JPEG Group/configure_.TXT new file mode 100644 index 0000000..3130894 --- /dev/null +++ b/Independent JPEG Group/configure_.TXT @@ -0,0 +1 @@ +#!/bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf. # Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Usage: configure [--srcdir=DIR] [--host=HOST] [--gas] [--nfp] # [--prefix=PREFIX] [--exec-prefix=PREFIX] [--with-PACKAGE[=VALUE]] # Ignores all args except --srcdir, --prefix, --exec-prefix, and # --with-PACKAGE[=VALUE] unless this script has special code to handle it. for arg do # Handle --exec-prefix with a space before the argument. if test x$next_exec_prefix = xyes; then exec_prefix=$arg; next_exec_prefix= # Handle --host with a space before the argument. elif test x$next_host = xyes; then next_host= # Handle --prefix with a space before the argument. elif test x$next_prefix = xyes; then prefix=$arg; next_prefix= # Handle --srcdir with a space before the argument. elif test x$next_srcdir = xyes; then srcdir=$arg; next_srcdir= else case $arg in # For backward compatibility, recognize -exec-prefix and --exec_prefix. -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* | --exec=* | --exe=* | --ex=* | --e=*) exec_prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- | --exec | --exe | --ex | --e) next_exec_prefix=yes ;; -gas | --gas | --ga | --g) ;; -host=* | --host=* | --hos=* | --ho=* | --h=*) ;; -host | --host | --hos | --ho | --h) next_host=yes ;; -nfp | --nfp | --nf) ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=`echo $arg | sed 's/[-a-z_]*=//'` ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) next_prefix=yes ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=* | --s=*) srcdir=`echo $arg | sed 's/[-a-z_]*=//'` ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr | --s) next_srcdir=yes ;; -with-* | --with-*) package=`echo $arg|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that aren't valid shell variable names. if test -n "`echo $package| sed 's/[-a-zA-Z0-9_]//g'`"; then echo "configure: $package: invalid package name" >&2; exit 1 fi package=`echo $package| sed 's/-/_/g'` case "$arg" in *=*) val="`echo $arg|sed 's/[^=]*=//'`" ;; *) val=1 ;; esac eval "with_$package='$val'" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb | --ver | --ve | --v) verbose=yes ;; *=*) varname=`echo $arg|sed -e 's/=.*//'` # Reject names that aren't valid shell variable names. if test -n "`echo $varname| sed 's/[a-zA-Z0-9_]//g'`"; then echo "configure: $varname: invalid shell variable name" >&2; exit 1 fi val="`echo $arg|sed 's/[^=]*=//'`" test -n "$verbose" && echo " setting shell variable $varname to $val" eval "$varname='$val'" eval "export $varname" ;; *) ;; esac fi done trap 'rm -fr conftest* confdefs* core; exit 1' 1 3 15 trap 'rm -f confdefs*' 0 # NLS nuisances. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). if test "${LC_ALL+set}" = 'set' ; then LC_ALL=C; export LC_ALL; fi if test "${LANG+set}" = 'set' ; then LANG=C; export LANG; fi rm -f conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h compile='${CC-cc} $CFLAGS conftest.c -o conftest $LIBS >/dev/null 2>&1' # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. unique_file=jcmaster.c # Find the source files, if location was not specified. if test -z "$srcdir"; then srcdirdefaulted=yes # Try the directory containing this script, then `..'. prog=$0 confdir=`echo $prog|sed 's%/[^/][^/]*$%%'` test "X$confdir" = "X$prog" && confdir=. srcdir=$confdir if test ! -r $srcdir/$unique_file; then srcdir=.. fi fi if test ! -r $srcdir/$unique_file; then if test x$srcdirdefaulted = xyes; then echo "configure: Can not find sources in \`${confdir}' or \`..'." 1>&2 else echo "configure: Can not find sources in \`${srcdir}'." 1>&2 fi exit 1 fi # Preserve a srcdir of `.' to avoid automounter screwups with pwd. # But we can't avoid them for `..', to make subdirectories work. case $srcdir in .|/*|~*) ;; *) srcdir=`cd $srcdir; pwd` ;; # Make relative path absolute. esac # Save the original args to write them into config.status later. configure_args="$*" if test -z "$CC"; then # Extract the first word of `gcc', so it can be a program name with args. set dummy gcc; word=$2 echo checking for $word IFS="${IFS= }"; saveifs="$IFS"; IFS="${IFS}:" for dir in $PATH; do test -z "$dir" && dir=. if test -f $dir/$word; then CC="gcc" break fi done IFS="$saveifs" fi test -z "$CC" && CC="cc" test -n "$CC" && test -n "$verbose" && echo " setting CC to $CC" # Find out if we are using GNU C, under whatever name. cat > conftest.c < conftest.out 2>&1 if egrep yes conftest.out >/dev/null 2>&1; then GCC=1 # For later tests. fi rm -f conftest* echo checking how to run the C preprocessor if test -z "$CPP"; then # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and ``${CC-cc}'' will simply confuse # make. It must be expanded now. CPP="${CC-cc} -E" cat > conftest.c < Syntax Error EOF err=`eval "($CPP conftest.c >/dev/null) 2>&1"` if test -z "$err"; then : else rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi test ".${verbose}" != "." && echo " setting CPP to $CPP" echo checking whether cross-compiling # If we cannot run a trivial program, we must be cross compiling. cat > conftest.c </dev/null; then : else cross_compiling=1 fi rm -fr conftest* echo checking for function prototypes cat > conftest.c <> confdefs.h DEFS="$DEFS -DHAVE_PROTOTYPES=" SEDDEFS="${SEDDEFS}\${SEDdA}HAVE_PROTOTYPES\${SEDdB}HAVE_PROTOTYPES\${SEDdC}\${SEDdD} \${SEDuA}HAVE_PROTOTYPES\${SEDuB}HAVE_PROTOTYPES\${SEDuC}\${SEDuD} \${SEDeA}HAVE_PROTOTYPES\${SEDeB}HAVE_PROTOTYPES\${SEDeC}\${SEDeD} " } else rm -rf conftest* echo Your compiler does not seem to know about function prototypes. echo Perhaps it needs a special switch to enable ANSI C mode. echo If so, we recommend running configure like this: echo " ./configure CC='cc -switch'" echo where -switch is the proper switch. fi rm -f conftest* echo checking for stddef.h cat > conftest.c < EOF err=`eval "($CPP conftest.c >/dev/null) 2>&1"` if test -z "$err"; then rm -rf conftest* { test -n "$verbose" && \ echo " defining" HAVE_STDDEF_H to be empty echo "#define" HAVE_STDDEF_H >> confdefs.h DEFS="$DEFS -DHAVE_STDDEF_H=" SEDDEFS="${SEDDEFS}\${SEDdA}HAVE_STDDEF_H\${SEDdB}HAVE_STDDEF_H\${SEDdC}\${SEDdD} \${SEDuA}HAVE_STDDEF_H\${SEDuB}HAVE_STDDEF_H\${SEDuC}\${SEDuD} \${SEDeA}HAVE_STDDEF_H\${SEDeB}HAVE_STDDEF_H\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking for stdlib.h cat > conftest.c < EOF err=`eval "($CPP conftest.c >/dev/null) 2>&1"` if test -z "$err"; then rm -rf conftest* { test -n "$verbose" && \ echo " defining" HAVE_STDLIB_H to be empty echo "#define" HAVE_STDLIB_H >> confdefs.h DEFS="$DEFS -DHAVE_STDLIB_H=" SEDDEFS="${SEDDEFS}\${SEDdA}HAVE_STDLIB_H\${SEDdB}HAVE_STDLIB_H\${SEDdC}\${SEDdD} \${SEDuA}HAVE_STDLIB_H\${SEDuB}HAVE_STDLIB_H\${SEDuC}\${SEDuD} \${SEDeA}HAVE_STDLIB_H\${SEDeB}HAVE_STDLIB_H\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking for string.h cat > conftest.c < EOF err=`eval "($CPP conftest.c >/dev/null) 2>&1"` if test -z "$err"; then : else rm -rf conftest* { test -n "$verbose" && \ echo " defining" NEED_BSD_STRINGS to be empty echo "#define" NEED_BSD_STRINGS >> confdefs.h DEFS="$DEFS -DNEED_BSD_STRINGS=" SEDDEFS="${SEDDEFS}\${SEDdA}NEED_BSD_STRINGS\${SEDdB}NEED_BSD_STRINGS\${SEDdC}\${SEDdD} \${SEDuA}NEED_BSD_STRINGS\${SEDuB}NEED_BSD_STRINGS\${SEDuC}\${SEDuD} \${SEDeA}NEED_BSD_STRINGS\${SEDeB}NEED_BSD_STRINGS\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking for size_t cat > conftest.c < #endif #ifdef HAVE_STDLIB_H #include #endif #include #ifdef NEED_BSD_STRINGS #include #else #include #endif typedef size_t my_size_t; int main() { exit(0); } int t() { my_size_t foovar; } EOF if eval $compile; then : else rm -rf conftest* echo checking for sys/types.h cat > conftest.c < EOF err=`eval "($CPP conftest.c >/dev/null) 2>&1"` if test -z "$err"; then rm -rf conftest* { test -n "$verbose" && \ echo " defining" NEED_SYS_TYPES_H to be empty echo "#define" NEED_SYS_TYPES_H >> confdefs.h DEFS="$DEFS -DNEED_SYS_TYPES_H=" SEDDEFS="${SEDDEFS}\${SEDdA}NEED_SYS_TYPES_H\${SEDdB}NEED_SYS_TYPES_H\${SEDdC}\${SEDdD} \${SEDuA}NEED_SYS_TYPES_H\${SEDuB}NEED_SYS_TYPES_H\${SEDuC}\${SEDuD} \${SEDeA}NEED_SYS_TYPES_H\${SEDeB}NEED_SYS_TYPES_H\${SEDeC}\${SEDeD} " } else rm -rf conftest* echo Type size_t is not defined in any of the usual places. echo Try putting '"typedef unsigned int size_t;"' in jconfig.h. fi rm -f conftest* fi rm -f conftest* echo checking for unsigned char cat > conftest.c <> confdefs.h DEFS="$DEFS -DHAVE_UNSIGNED_CHAR=" SEDDEFS="${SEDDEFS}\${SEDdA}HAVE_UNSIGNED_CHAR\${SEDdB}HAVE_UNSIGNED_CHAR\${SEDdC}\${SEDdD} \${SEDuA}HAVE_UNSIGNED_CHAR\${SEDuB}HAVE_UNSIGNED_CHAR\${SEDuC}\${SEDuD} \${SEDeA}HAVE_UNSIGNED_CHAR\${SEDeB}HAVE_UNSIGNED_CHAR\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking for unsigned short cat > conftest.c <> confdefs.h DEFS="$DEFS -DHAVE_UNSIGNED_SHORT=" SEDDEFS="${SEDDEFS}\${SEDdA}HAVE_UNSIGNED_SHORT\${SEDdB}HAVE_UNSIGNED_SHORT\${SEDdC}\${SEDdD} \${SEDuA}HAVE_UNSIGNED_SHORT\${SEDuB}HAVE_UNSIGNED_SHORT\${SEDuC}\${SEDuD} \${SEDeA}HAVE_UNSIGNED_SHORT\${SEDeB}HAVE_UNSIGNED_SHORT\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking for type void cat > conftest.c <> confdefs.h DEFS="$DEFS -Dvoid=char" SEDDEFS="${SEDDEFS}\${SEDdA}void\${SEDdB}void\${SEDdC}char\${SEDdD} \${SEDuA}void\${SEDuB}void\${SEDuC}char\${SEDuD} \${SEDeA}void\${SEDeB}void\${SEDeC}char\${SEDeD} " } fi rm -f conftest* prog='/* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset x; /* SunOS 4.1.1 cc rejects this. */ char const *const *ccp; char **p; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; ccp = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++ccp; p = (char**) ccp; ccp = (char const *const *) p; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25,17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; }' echo checking for lack of working const cat > conftest.c <> confdefs.h DEFS="$DEFS -Dconst=" SEDDEFS="${SEDDEFS}\${SEDdA}const\${SEDdB}const\${SEDdC}\${SEDdD} \${SEDuA}const\${SEDuB}const\${SEDuC}\${SEDuD} \${SEDeA}const\${SEDeB}const\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking for inline cat > conftest.c <> confdefs.h DEFS="$DEFS -DINLINE=inline" SEDDEFS="${SEDDEFS}\${SEDdA}INLINE\${SEDdB}INLINE\${SEDdC}inline\${SEDdD} \${SEDuA}INLINE\${SEDuB}INLINE\${SEDuC}inline\${SEDuD} \${SEDeA}INLINE\${SEDeB}INLINE\${SEDeC}inline\${SEDeD} " } else rm -rf conftest* cat > conftest.c <> confdefs.h DEFS="$DEFS -DINLINE=__inline__" SEDDEFS="${SEDDEFS}\${SEDdA}INLINE\${SEDdB}INLINE\${SEDdC}__inline__\${SEDdD} \${SEDuA}INLINE\${SEDuB}INLINE\${SEDuC}__inline__\${SEDuD} \${SEDeA}INLINE\${SEDeB}INLINE\${SEDeC}__inline__\${SEDeD} " } else rm -rf conftest* cat > conftest.c <> confdefs.h DEFS="$DEFS -DINLINE=__inline" SEDDEFS="${SEDDEFS}\${SEDdA}INLINE\${SEDdB}INLINE\${SEDdC}__inline\${SEDdD} \${SEDuA}INLINE\${SEDuB}INLINE\${SEDuC}__inline\${SEDuD} \${SEDeA}INLINE\${SEDeB}INLINE\${SEDeC}__inline\${SEDeD} " } else rm -rf conftest* { test -n "$verbose" && \ echo " defining" INLINE to be empty echo "#define" INLINE >> confdefs.h DEFS="$DEFS -DINLINE=" SEDDEFS="${SEDDEFS}\${SEDdA}INLINE\${SEDdB}INLINE\${SEDdC}\${SEDdD} \${SEDuA}INLINE\${SEDuB}INLINE\${SEDuC}\${SEDuD} \${SEDeA}INLINE\${SEDeB}INLINE\${SEDeC}\${SEDeD} " } fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* echo checking for broken incomplete types cat > conftest.c <> confdefs.h DEFS="$DEFS -DINCOMPLETE_TYPES_BROKEN=" SEDDEFS="${SEDDEFS}\${SEDdA}INCOMPLETE_TYPES_BROKEN\${SEDdB}INCOMPLETE_TYPES_BROKEN\${SEDdC}\${SEDdD} \${SEDuA}INCOMPLETE_TYPES_BROKEN\${SEDuB}INCOMPLETE_TYPES_BROKEN\${SEDuC}\${SEDuD} \${SEDeA}INCOMPLETE_TYPES_BROKEN\${SEDeB}INCOMPLETE_TYPES_BROKEN\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking for short external names cat > conftest.c <> confdefs.h DEFS="$DEFS -DNEED_SHORT_EXTERNAL_NAMES=" SEDDEFS="${SEDDEFS}\${SEDdA}NEED_SHORT_EXTERNAL_NAMES\${SEDdB}NEED_SHORT_EXTERNAL_NAMES\${SEDdC}\${SEDdD} \${SEDuA}NEED_SHORT_EXTERNAL_NAMES\${SEDuB}NEED_SHORT_EXTERNAL_NAMES\${SEDuC}\${SEDuD} \${SEDeA}NEED_SHORT_EXTERNAL_NAMES\${SEDeB}NEED_SHORT_EXTERNAL_NAMES\${SEDeC}\${SEDeD} " } fi rm -f conftest* echo checking to see if char is signed if test -n "$cross_compiling" then echo Assuming that char is signed on target machine. echo If it is unsigned, this will be a little bit inefficient. else cat > conftest.c </dev/null; then { test -n "$verbose" && \ echo " defining" CHAR_IS_UNSIGNED to be empty echo "#define" CHAR_IS_UNSIGNED >> confdefs.h DEFS="$DEFS -DCHAR_IS_UNSIGNED=" SEDDEFS="${SEDDEFS}\${SEDdA}CHAR_IS_UNSIGNED\${SEDdB}CHAR_IS_UNSIGNED\${SEDdC}\${SEDdD} \${SEDuA}CHAR_IS_UNSIGNED\${SEDuB}CHAR_IS_UNSIGNED\${SEDuC}\${SEDuD} \${SEDeA}CHAR_IS_UNSIGNED\${SEDeB}CHAR_IS_UNSIGNED\${SEDeC}\${SEDeD} " } fi fi rm -fr conftest* echo checking to see if right shift is signed if test -n "$cross_compiling" then echo Assuming that right shift is signed on target machine. else cat > conftest.c <> 4; if (res == 0x80817F4L) { /* expected result for unsigned */ return 0; /* right shift is unsigned */ } else if (res != -0x7F7E80CL) { /* expected result for signed */ printf("Right shift isn't acting as I expect it to.\n"); printf("I fear the JPEG software will not work at all.\n\n"); } return 1; /* right shift is signed */ } main() { exit(is_shifting_signed(-0x7F7E80B1L)); } EOF eval $compile if test -s conftest && (./conftest; exit) 2>/dev/null; then { test -n "$verbose" && \ echo " defining" RIGHT_SHIFT_IS_UNSIGNED to be empty echo "#define" RIGHT_SHIFT_IS_UNSIGNED >> confdefs.h DEFS="$DEFS -DRIGHT_SHIFT_IS_UNSIGNED=" SEDDEFS="${SEDDEFS}\${SEDdA}RIGHT_SHIFT_IS_UNSIGNED\${SEDdB}RIGHT_SHIFT_IS_UNSIGNED\${SEDdC}\${SEDdD} \${SEDuA}RIGHT_SHIFT_IS_UNSIGNED\${SEDuB}RIGHT_SHIFT_IS_UNSIGNED\${SEDuC}\${SEDuD} \${SEDeA}RIGHT_SHIFT_IS_UNSIGNED\${SEDeB}RIGHT_SHIFT_IS_UNSIGNED\${SEDeC}\${SEDeD} " } fi fi rm -fr conftest* echo checking to see if fopen accepts b spec if test -n "$cross_compiling" then echo Assuming that it does. else cat > conftest.c < main() { if (fopen("conftestdata", "wb") != NULL) exit(0); exit(1); } EOF eval $compile if test -s conftest && (./conftest; exit) 2>/dev/null; then : else { test -n "$verbose" && \ echo " defining" DONT_USE_B_MODE to be empty echo "#define" DONT_USE_B_MODE >> confdefs.h DEFS="$DEFS -DDONT_USE_B_MODE=" SEDDEFS="${SEDDEFS}\${SEDdA}DONT_USE_B_MODE\${SEDdB}DONT_USE_B_MODE\${SEDdC}\${SEDdD} \${SEDuA}DONT_USE_B_MODE\${SEDuB}DONT_USE_B_MODE\${SEDuC}\${SEDuD} \${SEDeA}DONT_USE_B_MODE\${SEDeB}DONT_USE_B_MODE\${SEDeC}\${SEDeD} " } fi fi rm -fr conftest* # Make sure to not get the incompatible SysV /etc/install and # /usr/sbin/install, which might be in PATH before a BSD-like install, # or the SunOS /usr/etc/install directory, or the AIX /bin/install, # or the AFS install, which mishandles nonexistent args, or # /usr/ucb/install on SVR4, which tries to use the nonexistent group # `staff'. On most BSDish systems install is in /usr/bin, not /usr/ucb # anyway. Sigh. if test "z${INSTALL}" = "z" ; then echo checking for install IFS="${IFS= }"; saveifs="$IFS"; IFS="${IFS}:" for dir in $PATH; do test -z "$dir" && dir=. case $dir in /etc|/usr/sbin|/usr/etc|/usr/afsws/bin|/usr/ucb) ;; *) if test -f $dir/installbsd; then INSTALL="$dir/installbsd -c" # OSF1 INSTALL_PROGRAM='$(INSTALL)' INSTALL_DATA='$(INSTALL) -m 644' break fi if test -f $dir/install; then if grep dspmsg $dir/install >/dev/null 2>&1; then : # AIX else INSTALL="$dir/install -c" INSTALL_PROGRAM='$(INSTALL)' INSTALL_DATA='$(INSTALL) -m 644' break fi fi ;; esac done IFS="$saveifs" fi INSTALL=${INSTALL-cp} test -n "$verbose" && echo " setting INSTALL to $INSTALL" INSTALL_PROGRAM=${INSTALL_PROGRAM-'$(INSTALL)'} test -n "$verbose" && echo " setting INSTALL_PROGRAM to $INSTALL_PROGRAM" INSTALL_DATA=${INSTALL_DATA-'$(INSTALL)'} test -n "$verbose" && echo " setting INSTALL_DATA to $INSTALL_DATA" if test -z "$RANLIB"; then # Extract the first word of `ranlib', so it can be a program name with args. set dummy ranlib; word=$2 echo checking for $word IFS="${IFS= }"; saveifs="$IFS"; IFS="${IFS}:" for dir in $PATH; do test -z "$dir" && dir=. if test -f $dir/$word; then RANLIB="ranlib" break fi done IFS="$saveifs" fi test -z "$RANLIB" && RANLIB=":" test -n "$RANLIB" && test -n "$verbose" && echo " setting RANLIB to $RANLIB" # check whether --with-maxmem was given withval="$with_maxmem" if test -n "$withval"; then DEFAULTMAXMEM=`expr $withval \* 1048576` { test -n "$verbose" && \ echo " defining" DEFAULT_MAX_MEM to be ${DEFAULTMAXMEM} echo "#define" DEFAULT_MAX_MEM ${DEFAULTMAXMEM} >> confdefs.h DEFS="$DEFS -DDEFAULT_MAX_MEM=${DEFAULTMAXMEM}" SEDDEFS="${SEDDEFS}\${SEDdA}DEFAULT_MAX_MEM\${SEDdB}DEFAULT_MAX_MEM\${SEDdC}${DEFAULTMAXMEM}\${SEDdD} \${SEDuA}DEFAULT_MAX_MEM\${SEDuB}DEFAULT_MAX_MEM\${SEDuC}${DEFAULTMAXMEM}\${SEDuD} \${SEDeA}DEFAULT_MAX_MEM\${SEDeB}DEFAULT_MAX_MEM\${SEDeC}${DEFAULTMAXMEM}\${SEDeD} " } echo checking for 'tmpfile()' cat > conftest.c < int main() { exit(0); } int t() { FILE * tfile = tmpfile(); } EOF if eval $compile; then rm -rf conftest* MEMORYMGR="jmemansi.o" else rm -rf conftest* MEMORYMGR="jmemname.o" { test -n "$verbose" && \ echo " defining" NEED_SIGNAL_CATCHER to be empty echo "#define" NEED_SIGNAL_CATCHER >> confdefs.h DEFS="$DEFS -DNEED_SIGNAL_CATCHER=" SEDDEFS="${SEDDEFS}\${SEDdA}NEED_SIGNAL_CATCHER\${SEDdB}NEED_SIGNAL_CATCHER\${SEDdC}\${SEDdD} \${SEDuA}NEED_SIGNAL_CATCHER\${SEDuB}NEED_SIGNAL_CATCHER\${SEDuC}\${SEDuD} \${SEDeA}NEED_SIGNAL_CATCHER\${SEDeB}NEED_SIGNAL_CATCHER\${SEDeC}\${SEDeD} " } echo checking for 'mktemp()' cat > conftest.c <> confdefs.h DEFS="$DEFS -DNO_MKTEMP=" SEDDEFS="${SEDDEFS}\${SEDdA}NO_MKTEMP\${SEDdB}NO_MKTEMP\${SEDdC}\${SEDdD} \${SEDuA}NO_MKTEMP\${SEDuB}NO_MKTEMP\${SEDuC}\${SEDuD} \${SEDeA}NO_MKTEMP\${SEDeB}NO_MKTEMP\${SEDeC}\${SEDeD} " } fi rm -f conftest* fi rm -f conftest* else MEMORYMGR="jmemnobs.o" fi # Prepare to massage makefile.auto correctly. case "$DEFS" in *HAVE_PROTOTYPES*) ANSI2KNR="" ISANSICOM="# " ;; *) ANSI2KNR="ansi2knr" ISANSICOM="" ;; esac case "$DEFS" in *NEED_BSD_STRINGS*) ANSI2KNRFLAGS="-DBSD" ;; *) ANSI2KNRFLAGS="" ;; esac # Set default prefixes. if test -n "$prefix"; then test -z "$exec_prefix" && exec_prefix='${prefix}' prsub="s%^prefix\\([ ]*\\)=\\([ ]*\\).*$%prefix\\1=\\2$prefix%" fi if test -n "$exec_prefix"; then prsub="$prsub s%^exec_prefix\\([ ]*\\)=\\([ ]*\\).*$%exec_prefix\\1=\\2$exec_prefix%" fi # Quote sed substitution magic chars in DEFS. cat >conftest.def < config.status </dev/null | sed 1q`: # # $0 $configure_args for arg do case "\$arg" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo running \${CONFIG_SHELL-/bin/sh} $0 $configure_args exec \${CONFIG_SHELL-/bin/sh} $0 $configure_args ;; *) echo "Usage: config.status --recheck" 2>&1; exit 1 ;; esac done trap 'rm -fr Makefile jconfig.h conftest*; exit 1' 1 3 15 CC='$CC' CPP='$CPP' INSTALL='$INSTALL' INSTALL_PROGRAM='$INSTALL_PROGRAM' INSTALL_DATA='$INSTALL_DATA' RANLIB='$RANLIB' MEMORYMGR='$MEMORYMGR' ANSI2KNR='$ANSI2KNR' ISANSICOM='$ISANSICOM' ANSI2KNRFLAGS='$ANSI2KNRFLAGS' LIBS='$LIBS' srcdir='$srcdir' prefix='$prefix' exec_prefix='$exec_prefix' prsub='$prsub' extrasub='$extrasub' EOF cat >> config.status <<\EOF top_srcdir=$srcdir CONFIG_FILES=${CONFIG_FILES-"Makefile"} for file in .. ${CONFIG_FILES}; do if test "x$file" != x..; then srcdir=$top_srcdir # Remove last slash and all that follows it. Not all systems have dirname. dir=`echo $file|sed 's%/[^/][^/]*$%%'` if test "$dir" != "$file"; then test "$top_srcdir" != . && srcdir=$top_srcdir/$dir test ! -d $dir && mkdir $dir fi echo creating $file rm -f $file echo "# Generated automatically from `echo $file|sed 's|.*/||'`.auto by configure." > $file sed -e " $prsub $extrasub s%@CC@%$CC%g s%@CPP@%$CPP%g s%@INSTALL@%$INSTALL%g s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g s%@INSTALL_DATA@%$INSTALL_DATA%g s%@RANLIB@%$RANLIB%g s%@MEMORYMGR@%$MEMORYMGR%g s%@ANSI2KNR@%$ANSI2KNR%g s%@ISANSICOM@%$ISANSICOM%g s%@ANSI2KNRFLAGS@%$ANSI2KNRFLAGS%g s%@LIBS@%$LIBS%g s%@srcdir@%$srcdir%g s%@DEFS@%-DHAVE_CONFIG_H%" $top_srcdir/makefile.auto >> $file fi; done CONFIG_HEADERS=${CONFIG_HEADERS-"jconfig.h"} for file in .. ${CONFIG_HEADERS}; do if test "x$file" != x..; then echo creating $file # These sed commands are put into SEDDEFS when defining a macro. # They are broken into pieces to make the sed script easier to manage. # They are passed to sed as "A NAME B NAME C VALUE D", where NAME # is the cpp macro being defined and VALUE is the value it is being given. # Each defining turns into a single global substitution command. # # SEDd sets the value in "#define NAME VALUE" lines. SEDdA='s@^\([ ]*\)#\([ ]*define[ ][ ]*\)' SEDdB='\([ ][ ]*\)[^ ]*@\1#\2' SEDdC='\3' SEDdD='@g' # SEDu turns "#undef NAME" with trailing blanks into "#define NAME VALUE". SEDuA='s@^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' SEDuB='\([ ]\)@\1#\2define\3' SEDuC=' ' SEDuD='\4@g' # SEDe turns "#undef NAME" without trailing blanks into "#define NAME VALUE". SEDeA='s@^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' SEDeB='$@\1#\2define\3' SEDeC=' ' SEDeD='@g' rm -f conftest.sed EOF # Turn off quoting long enough to insert the sed commands. rm -f conftest.sh cat > conftest.sh < conftest.s1 # Like head -20. sed 1,${maxshlines}d conftest.sh > conftest.s2 # Like tail +21. # Write a limited-size here document to append to conftest.sed. echo 'cat >> conftest.sed <> config.status cat conftest.s1 >> config.status echo 'CONFEOF' >> config.status rm -f conftest.s1 conftest.sh mv conftest.s2 conftest.sh done rm -f conftest.sh # Now back to your regularly scheduled config.status. cat >> config.status <<\EOF # This sed command replaces #undef's with comments. This is necessary, for # example, in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it in # jconfig.h. cat >> conftest.sed <<\CONFEOF CONFEOF rm -f conftest.h # Break up the sed commands because old seds have small limits. maxsedlines=20 cp $top_srcdir/jconfig.auto conftest.h1 while : do lines=`grep -c . conftest.sed` if test -z "$lines" || test "$lines" -eq 0; then break; fi rm -f conftest.s1 conftest.s2 conftest.h2 sed ${maxsedlines}q conftest.sed > conftest.s1 # Like head -20. sed 1,${maxsedlines}d conftest.sed > conftest.s2 # Like tail +21. sed -f conftest.s1 < conftest.h1 > conftest.h2 rm -f conftest.s1 conftest.h1 conftest.sed mv conftest.h2 conftest.h1 mv conftest.s2 conftest.sed done rm -f conftest.sed conftest.h echo "/* $file. Generated automatically by configure. */" > conftest.h cat conftest.h1 >> conftest.h rm -f conftest.h1 if cmp -s $file conftest.h 2>/dev/null; then # The file exists and we would not be changing it. echo "$file is unchanged" rm -f conftest.h else rm -f $file mv conftest.h $file fi fi; done exit 0 EOF chmod +x config.status ${CONFIG_SHELL-/bin/sh} config.status \ No newline at end of file diff --git a/Independent JPEG Group/djpeg.1 b/Independent JPEG Group/djpeg.1 new file mode 100644 index 0000000..8c69b83 --- /dev/null +++ b/Independent JPEG Group/djpeg.1 @@ -0,0 +1 @@ +.TH DJPEG 1 "24 April 1994" .SH NAME djpeg \- decompress a JPEG file to an image file .SH SYNOPSIS .B djpeg [ .BI \-colors " N" ] [ .B \-grayscale ] [ .BI \-scale " M/N" ] [ .B \-gif ] [ .B \-pnm ] [ .B \-rle ] [ .B \-targa ] [ .B \-blocksmooth ] [ .BI \-maxmemory " N" ] [ .B \-nodither ] [ .B \-nosmooth ] [ .B \-onepass ] [ .B \-verbose ] [ .B \-debug ] [ .I filename ] .LP .SH DESCRIPTION .LP .B djpeg decompresses the named JPEG file, or the standard input if no file is named, and produces an image file on the standard output. PBMPLUS (PPM/PGM), GIF, Targa, or RLE (Utah Raster Toolkit) output format can be selected. (RLE is supported only if the URT library is available.) .SH OPTIONS All switch names may be abbreviated; for example, .B \-grayscale may be written .B \-gray or .BR \-gr . Most of the "basic" switches can be abbreviated to as little as one letter. Upper and lower case are equivalent (thus .B \-GIF is the same as .BR \-gif ). British spellings are also accepted (e.g., .BR \-greyscale ), though for brevity these are not mentioned below. .PP The basic switches are: .TP .BI \-colors " N" Reduce image to at most N colors. This reduces the number of colors used in the output image, so that it can be displayed on a colormapped display or stored in a colormapped file format. For example, if you have an 8-bit display, you'd need to reduce to 256 or fewer colors. .TP .BI \-quantize " N" Same as .BR \-colors . .B \-colors is the recommended name, .B \-quantize is provided only for backwards compatibility. .TP .B \-grayscale Force gray-scale output even if JPEG file is color. Useful for viewing on monochrome displays; also, .B djpeg runs noticeably faster in this mode. .TP .BI \-scale " M/N" Scale the output image by a factor M/N. Currently the scale factor must be 1/1, 1/2, 1/4, or 1/8. Scaling is handy if the image is larger than your screen; also, .B djpeg runs much faster when scaling down the output. .TP .B \-gif Select GIF output format. Since GIF does not support more than 256 colors, .B \-colors 256 is assumed (unless you specify a smaller number of colors). .TP .B \-pnm Select PBMPLUS (PPM/PGM) output format (this is the default format). PGM is emitted if the JPEG file is gray-scale or if .B \-grayscale is specified; otherwise PPM is emitted. .TP .B \-rle Select RLE output format. (Requires URT library.) .TP .B \-targa Select Targa output format. Gray-scale format is emitted if the JPEG file is gray-scale or if .B \-grayscale is specified; otherwise, colormapped format is emitted if .B \-colors is specified; otherwise, 24-bit full-color format is emitted. .PP Switches for advanced users: .TP .B \-blocksmooth Perform cross-block smoothing. This is slow, quite memory-intensive, and only seems to improve the image at very low quality settings (\fB\-quality\fR 10 to 20 or so). At normal quality settings it may make the image worse. .TP .BI \-maxmemory " N" Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, .B \-max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. .TP .B \-nodither Do not use dithering in color quantization. By default, Floyd-Steinberg dithering is applied when quantizing colors, but on some images dithering may result in objectionable "graininess". If that happens, you can turn off dithering with .BR \-nodither . .TP .B \-nosmooth Use a faster, lower-quality upsampling routine. .TP .B \-onepass Use one-pass instead of two-pass color quantization. The one-pass method is faster and needs less memory, but it produces a lower-quality image. .B \-onepass is ignored unless you also say .B \-colors .IR N . Also, the one-pass method is always used for gray-scale output (the two-pass method is no improvement then). .TP .B \-verbose Enable debug printout. More .BR \-v 's give more output. Also, version information is printed at startup. .TP .B \-debug Same as .BR \-verbose . .SH EXAMPLES .LP This example decompresses the JPEG file foo.jpg, automatically quantizes to 256 colors, and saves the output in GIF format in foo.gif: .IP .B djpeg \-gif .I foo.jpg .B > .I foo.gif .SH HINTS To get a quick preview of an image, use the .B \-grayscale and/or .B \-scale switches. .B \-grayscale \-scale 1/8 is the fastest option. .SH ENVIRONMENT .TP .B JPEGMEM If this environment variable is set, its value is the default memory limit. The value is specified as described for the .B \-maxmemory switch. .B JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit .BR \-maxmemory . .SH SEE ALSO .BR cjpeg (1) .br .BR ppm (5), .BR pgm (5) .br Wallace, Gregory K. "The JPEG Still Picture Compression Standard", Communications of the ACM, April 1991 (vol. 34, no. 4), pp. 30-44. .SH AUTHOR Independent JPEG Group .SH BUGS Arithmetic coding is not supported for legal reasons. .PP Still not as fast as we'd like. \ No newline at end of file diff --git a/Independent JPEG Group/djpeg.c b/Independent JPEG Group/djpeg.c new file mode 100644 index 0000000..f51f05d --- /dev/null +++ b/Independent JPEG Group/djpeg.c @@ -0,0 +1 @@ +/* * djpeg.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a command-line user interface for the JPEG decompressor. * It should work on any system with Unix- or MS-DOS-style command lines. * * Two different command line styles are permitted, depending on the * compile-time switch TWO_FILE_COMMANDLINE: * djpeg [options] inputfile outputfile * djpeg [options] [inputfile] * In the second style, output is always to standard output, which you'd * normally redirect to a file or pipe to some other program. Input is * either from a named file or from standard input (typically redirected). * The second style is convenient on Unix but is unhelpful on systems that * don't support pipes. Also, you MUST use the first style if your system * doesn't do binary I/O to stdin/stdout. * To simplify script writing, the "-outfile" switch is provided. The syntax * djpeg [options] -outfile outputfile inputfile * works regardless of which command line style is used. */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #define JMAKE_MSG_TABLE #include "cderror.h" /* create message string table */ #include "jversion.h" /* for version message */ #include /* to declare isupper(), tolower() */ #ifdef NEED_SIGNAL_CATCHER #include /* to declare signal() */ #endif #ifdef USE_SETMODE #include /* to declare setmode() */ #endif #ifdef THINK_C #include /* command-line reader for Macintosh */ #endif #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #define WRITE_BINARY "w" #else #define READ_BINARY "rb" #define WRITE_BINARY "wb" #endif #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif #ifndef EXIT_SUCCESS #ifdef VMS #define EXIT_SUCCESS 1 /* VMS is very nonstandard */ #else #define EXIT_SUCCESS 0 #endif #endif #ifndef EXIT_WARNING #ifdef VMS #define EXIT_WARNING 1 /* VMS is very nonstandard */ #else #define EXIT_WARNING 2 #endif #endif /* * This list defines the known output image formats * (not all of which need be supported by a given version). * You can change the default output format by defining DEFAULT_FMT; * indeed, you had better do so if you undefine PPM_SUPPORTED. */ typedef enum { FMT_GIF, /* GIF format */ FMT_PPM, /* PPM/PGM (PBMPLUS formats) */ FMT_RLE, /* RLE format */ FMT_TARGA, /* Targa format */ FMT_TIFF /* TIFF format */ } IMAGE_FORMATS; #ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */ #define DEFAULT_FMT FMT_PPM #endif static IMAGE_FORMATS requested_fmt; /* * Signal catcher to ensure that temporary files are removed before aborting. * NB: for Amiga Manx C this is actually a global routine named _abort(); * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus... */ #ifdef NEED_SIGNAL_CATCHER static j_common_ptr sig_cinfo; GLOBAL void signal_catcher (int signum) { if (sig_cinfo != NULL) { if (sig_cinfo->err != NULL) /* turn off trace output */ sig_cinfo->err->trace_level = 0; jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */ } exit(EXIT_FAILURE); } #endif /* * Argument-parsing code. * The switch parser is designed to be useful with DOS-style command line * syntax, ie, intermixed switches and file names, where only the switches * to the left of a given file name affect processing of that file. * The main program in this file doesn't actually use this capability... */ static char * progname; /* program name for error messages */ static char * outfilename; /* for -outfile switch */ LOCAL void usage (void) /* complain about bad command line */ { fprintf(stderr, "usage: %s [switches] ", progname); #ifdef TWO_FILE_COMMANDLINE fprintf(stderr, "inputfile outputfile\n"); #else fprintf(stderr, "[inputfile]\n"); #endif fprintf(stderr, "Switches (names may be abbreviated):\n"); fprintf(stderr, " -colors N Reduce image to no more than N colors\n"); #ifdef GIF_SUPPORTED fprintf(stderr, " -gif Select GIF output format\n"); #endif fprintf(stderr, " -grayscale Force grayscale output\n"); #ifdef PPM_SUPPORTED fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format (default)\n"); #endif fprintf(stderr, " -quantize N Same as -colors N\n"); #ifdef RLE_SUPPORTED fprintf(stderr, " -rle Select Utah RLE output format\n"); #endif #ifdef IDCT_SCALING_SUPPORTED fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n"); #endif #ifdef TARGA_SUPPORTED fprintf(stderr, " -targa Select Targa output format\n"); #endif fprintf(stderr, "Switches for advanced users:\n"); #ifdef BLOCK_SMOOTHING_SUPPORTED fprintf(stderr, " -blocksmooth Apply cross-block smoothing\n"); #endif fprintf(stderr, " -nodither Don't use dithering in quantization\n"); fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n"); #ifdef QUANT_1PASS_SUPPORTED fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n"); #endif fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n"); fprintf(stderr, " -verbose or -debug Emit debug output\n"); exit(EXIT_FAILURE); } LOCAL boolean keymatch (char * arg, const char * keyword, int minchars) /* Case-insensitive matching of (possibly abbreviated) keyword switches. */ /* keyword is the constant keyword (must be lower case already), */ /* minchars is length of minimum legal abbreviation. */ { register int ca, ck; register int nmatched = 0; while ((ca = *arg++) != '\0') { if ((ck = *keyword++) == '\0') return FALSE; /* arg longer than keyword, no good */ if (isupper(ca)) /* force arg to lcase (assume ck is already) */ ca = tolower(ca); if (ca != ck) return FALSE; /* no good */ nmatched++; /* count matched characters */ } /* reached end of argument; fail if it's too short for unique abbrev */ if (nmatched < minchars) return FALSE; return TRUE; /* A-OK */ } LOCAL int parse_switches (j_decompress_ptr cinfo, int last_file_arg_seen, int argc, char **argv) /* Initialize cinfo with default switch settings, then parse option switches. * Returns argv[] index of first file-name argument (== argc if none). * Any file names with indexes <= last_file_arg_seen are ignored; * they have presumably been processed in a previous iteration. * (Pass 0 for last_file_arg_seen on the first or only iteration.) */ { int argn; char * arg; /* Set up default JPEG parameters. */ requested_fmt = DEFAULT_FMT; /* set default output file format */ outfilename = NULL; cinfo->err->trace_level = 0; /* Scan command line options, adjust parameters */ for (argn = 1; argn < argc; argn++) { arg = argv[argn]; if (*arg != '-') { /* Not a switch, must be a file name argument */ if (argn <= last_file_arg_seen) { outfilename = NULL; /* -outfile applies to just one input file */ continue; /* ignore this name if previously processed */ } break; /* else done parsing switches */ } arg++; /* advance past switch marker character */ if (keymatch(arg, "blocksmooth", 1)) { /* Enable cross-block smoothing. */ cinfo->do_block_smoothing = TRUE; } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) || keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) { /* Do color quantization. */ int val; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%d", &val) != 1) usage(); cinfo->desired_number_of_colors = val; cinfo->quantize_colors = TRUE; } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) { /* Enable debug printouts. */ /* On first -d, print version identification */ static boolean printed_version = FALSE; if (! printed_version) { fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n", JVERSION, JCOPYRIGHT); printed_version = TRUE; } cinfo->err->trace_level++; } else if (keymatch(arg, "gif", 1)) { /* GIF output format. */ requested_fmt = FMT_GIF; } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) { /* Force monochrome output. */ cinfo->out_color_space = JCS_GRAYSCALE; } else if (keymatch(arg, "maxmemory", 1)) { /* Maximum memory in Kb (or Mb with 'm'). */ long lval; char ch = 'x'; if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1) usage(); if (ch == 'm' || ch == 'M') lval *= 1000L; cinfo->mem->max_memory_to_use = lval * 1000L; } else if (keymatch(arg, "nodither", 3)) { /* Suppress dithering in color quantization. */ cinfo->use_dithering = FALSE; } else if (keymatch(arg, "nosmooth", 3)) { /* Suppress fancy upsampling */ cinfo->do_fancy_upsampling = FALSE; } else if (keymatch(arg, "onepass", 1)) { /* Use fast one-pass quantization. */ cinfo->two_pass_quantize = FALSE; } else if (keymatch(arg, "outfile", 3)) { /* Set output file name. */ if (++argn >= argc) /* advance to next argument */ usage(); outfilename = argv[argn]; /* save it away for later use */ } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) { /* PPM/PGM output format. */ requested_fmt = FMT_PPM; } else if (keymatch(arg, "rle", 1)) { /* RLE output format. */ requested_fmt = FMT_RLE; } else if (keymatch(arg, "scale", 1)) { /* Scale the output image by a fraction M/N. */ if (++argn >= argc) /* advance to next argument */ usage(); if (sscanf(argv[argn], "%u/%u", &cinfo->scale_num, &cinfo->scale_denom) != 2) usage(); } else if (keymatch(arg, "targa", 1)) { /* Targa output format. */ requested_fmt = FMT_TARGA; } else { usage(); /* bogus switch */ } } return argn; /* return index of next arg (file name) */ } /* * The main program. */ GLOBAL int main (int argc, char **argv) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; int file_index; djpeg_dest_ptr dest_mgr = NULL; FILE * input_file; FILE * output_file; JDIMENSION num_scanlines; /* On Mac, fetch a command line. */ #ifdef THINK_C argc = ccommand(&argv); #endif progname = argv[0]; /* Initialize the JPEG decompression object with default error handling. */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); /* Add some application-specific error messages (from cderror.h) */ jerr.addon_message_table = addon_message_table; jerr.first_addon_message = JMSG_FIRSTADDONCODE; jerr.last_addon_message = JMSG_LASTADDONCODE; /* Now safe to enable signal catcher. */ #ifdef NEED_SIGNAL_CATCHER sig_cinfo = (j_common_ptr) &cinfo; signal(SIGINT, signal_catcher); #ifdef SIGTERM /* not all systems have SIGTERM */ signal(SIGTERM, signal_catcher); #endif #endif /* Scan command line to find file names. */ /* It is convenient to use just one switch-parsing routine, but the switch * values read here are ignored; we will rescan the switches after opening * the input file. */ file_index = parse_switches(&cinfo, 0, argc, argv); #ifdef TWO_FILE_COMMANDLINE /* Must have either -outfile switch or explicit output file name */ if (outfilename == NULL) { if (file_index != argc-2) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } outfilename = argv[file_index+1]; } else { if (file_index != argc-1) { fprintf(stderr, "%s: must name one input and one output file\n", progname); usage(); } } #else /* Unix style: expect zero or one file name */ if (file_index < argc-1) { fprintf(stderr, "%s: only one input file\n", progname); usage(); } #endif /* TWO_FILE_COMMANDLINE */ /* Open the input file. */ if (file_index < argc) { if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]); exit(EXIT_FAILURE); } } else { /* default input file is stdin */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdin), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdin\n", progname); exit(EXIT_FAILURE); } #else input_file = stdin; #endif } /* Open the output file. */ if (outfilename != NULL) { if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, outfilename); exit(EXIT_FAILURE); } } else { /* default output file is stdout */ #ifdef USE_SETMODE /* need to hack file mode? */ setmode(fileno(stdout), O_BINARY); #endif #ifdef USE_FDOPEN /* need to re-open in binary mode? */ if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { fprintf(stderr, "%s: can't open stdout\n", progname); exit(EXIT_FAILURE); } #else output_file = stdout; #endif } #ifdef PROGRESS_REPORT /* Enable progress display, unless trace output is on */ if (jerr.trace_level == 0) dc_methods.progress_monitor = progress_monitor; #endif /* Specify data source for decompression */ jpeg_stdio_src(&cinfo, input_file); /* Read file header, set default decompression parameters */ (void) jpeg_read_header(&cinfo, TRUE); /* Adjust default decompression parameters by re-parsing the options */ file_index = parse_switches(&cinfo, 0, argc, argv); /* Initialize the output module now to let it override any crucial * option settings (for instance, GIF wants to force color quantization). */ switch (requested_fmt) { #ifdef GIF_SUPPORTED case FMT_GIF: dest_mgr = jinit_write_gif(&cinfo); break; #endif #ifdef PPM_SUPPORTED case FMT_PPM: dest_mgr = jinit_write_ppm(&cinfo); break; #endif #ifdef RLE_SUPPORTED case FMT_RLE: dest_mgr = jinit_write_rle(&cinfo); break; #endif #ifdef TARGA_SUPPORTED case FMT_TARGA: dest_mgr = jinit_write_targa(&cinfo); break; #endif default: ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT); break; } dest_mgr->output_file = output_file; /* Start decompressor */ jpeg_start_decompress(&cinfo); /* Write output file header */ (*dest_mgr->start_output) (&cinfo, dest_mgr); /* Process data */ while (cinfo.output_scanline < cinfo.output_height) { num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer, dest_mgr->buffer_height); (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines); } /* Finish decompression and release memory */ (*dest_mgr->finish_output) (&cinfo, dest_mgr); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); #ifdef PROGRESS_REPORT /* Clear away progress display */ if (jerr.trace_level == 0) { fprintf(stderr, "\r \r"); fflush(stderr); } #endif /* All done. */ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS); return 0; /* suppress no-return-value warnings */ } \ No newline at end of file diff --git a/Independent JPEG Group/example.c b/Independent JPEG Group/example.c new file mode 100644 index 0000000..2f986a5 --- /dev/null +++ b/Independent JPEG Group/example.c @@ -0,0 +1 @@ +/* * example.c * * This file illustrates how to use the IJG code as a subroutine library * to read or write JPEG image files. You should look at this code in * conjunction with the documentation file libjpeg.doc. * * This code will not do anything useful as-is, but it may be helpful as a * skeleton for constructing routines that call the JPEG library. * * We present these routines in the same coding style used in the JPEG code * (ANSI function definitions, etc); but you are of course free to code your * routines in a different style if you prefer. */ #include /* * Include file for users of JPEG library. * You will need to have included system headers that define at least * the typedefs FILE and size_t before you can include jpeglib.h. * (stdio.h is sufficient on ANSI-conforming systems.) * You may also wish to include "jerror.h". */ #include "jpeglib.h" /* * is used for the optional error recovery mechanism shown in * the second part of the example. */ #include /******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/ /* This half of the example shows how to feed data into the JPEG compressor. * We present a minimal version that does not worry about refinements such * as error recovery (the JPEG code will just exit() if it gets an error). */ /* * IMAGE DATA FORMATS: * * The standard input image format is a rectangular array of pixels, with * each pixel having the same number of "component" values (color channels). * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars). * If you are working with color data, then the color values for each pixel * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit * RGB color. * * For this example, we'll assume that this data structure matches the way * our application has stored the image in memory, so we can just pass a * pointer to our image buffer. In particular, let's say that the image is * RGB color and is described by: */ extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */ extern int image_height; /* Number of rows in image */ extern int image_width; /* Number of columns in image */ /* * Sample routine for JPEG compression. We assume that the target file name * and a compression quality factor are passed in. */ GLOBAL void write_JPEG_file (char * filename, int quality) { /* This struct contains the JPEG compression parameters and pointers to * working space (which is allocated as needed by the JPEG library). * It is possible to have several such structures, representing multiple * compression/decompression processes, in existence at once. We refer * to any one struct (and its associated working data) as a "JPEG object". */ struct jpeg_compress_struct cinfo; /* This struct represents a JPEG error handler. It is declared separately * because applications often want to supply a specialized error handler * (see the second half of this file for an example). But here we just * take the easy way out and use the standard error handler, which will * print a message on stderr and call exit() if compression fails. */ struct jpeg_error_mgr jerr; /* More stuff */ FILE * outfile; /* target file */ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ int row_stride; /* physical row width in image buffer */ /* Step 1: allocate and initialize JPEG compression object */ /* We have to set up the error handler first, in case the initialization * step fails. (Unlikely, but it could happen if you are out of memory.) * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ cinfo.err = jpeg_std_error(&jerr); /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ /* Here we use the library-supplied code to send compressed data to a * stdio stream. You can also write your own code to do something else. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to write binary files. */ if ((outfile = fopen(filename, "wb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); exit(1); } jpeg_stdio_dest(&cinfo, outfile); /* Step 3: set parameters for compression */ /* First we supply a description of the input image. * Four fields of the cinfo struct must be filled in: */ cinfo.image_width = image_width; /* image width and height, in pixels */ cinfo.image_height = image_height; cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ /* Now use the library's routine to set default compression parameters. * (You must set at least cinfo.in_color_space before calling this, * since the defaults depend on the source color space.) */ jpeg_set_defaults(&cinfo); /* Now you can set any non-default parameters you wish to. * Here we just illustrate the use of quality (quantization table) scaling: */ jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); /* Step 4: Start compressor */ /* TRUE ensures that we will write a complete interchange-JPEG file. * Pass TRUE unless you are very sure of what you're doing. */ jpeg_start_compress(&cinfo, TRUE); /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ /* Here we use the library's state variable cinfo.next_scanline as the * loop counter, so that we don't have to keep track ourselves. * To keep things simple, we pass one scanline per call; you can pass * more if you wish, though. */ row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); /* After finish_compress, we can close the output file. */ fclose(outfile); /* Step 7: release JPEG compression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_compress(&cinfo); /* And we're done! */ } /* * SOME FINE POINTS: * * In the above loop, we ignored the return value of jpeg_write_scanlines, * which is the number of scanlines actually written. We could get away * with this because we were only relying on the value of cinfo.next_scanline, * which will be incremented correctly. If you maintain additional loop * variables then you should be careful to increment them properly. * Actually, for output to a stdio stream you needn't worry, because * then jpeg_write_scanlines will write all the lines passed (or else exit * with a fatal error). Partial writes can only occur if you use a data * destination module that can demand suspension of the compressor. * (If you don't know what that's for, you don't need it.) * * If the compressor requires full-image buffers (for entropy-coding * optimization or a noninterleaved JPEG file), it will create temporary * files for anything that doesn't fit within the maximum-memory setting. * (Note that temp files are NOT needed if you use the default parameters.) * On some systems you may need to set up a signal handler to ensure that * temporary files are deleted if the program is interrupted. See libjpeg.doc. * * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG * files to be compatible with everyone else's. If you cannot readily read * your data in that order, you'll need an intermediate array to hold the * image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top * source data using the JPEG code's internal virtual-array mechanisms. */ /******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/ /* This half of the example shows how to read data from the JPEG decompressor. * It's a bit more refined than the above, in that we show: * (a) how to modify the JPEG library's standard error-reporting behavior; * (b) how to allocate workspace using the library's memory manager. * * Just to make this example a little different from the first one, we'll * assume that we do not intend to put the whole image into an in-memory * buffer, but to send it line-by-line someplace else. We need a one- * scanline-high JSAMPLE array as a work buffer, and we will let the JPEG * memory manager allocate it for us. This approach is actually quite useful * because we don't need to remember to deallocate the buffer separately: it * will go away automatically when the JPEG object is cleaned up. */ /* * ERROR HANDLING: * * The JPEG library's standard error handler (jerror.c) is divided into * several "methods" which you can override individually. This lets you * adjust the behavior without duplicating a lot of code, which you might * have to update with each future release. * * Our example here shows how to override the "error_exit" method so that * control is returned to the library's caller when a fatal error occurs, * rather than calling exit() as the standard error_exit method does. * * We use C's setjmp/longjmp facility to return control. This means that the * routine which calls the JPEG library must first execute a setjmp() call to * establish the return point. We want the replacement error_exit to do a * longjmp(). But we need to make the setjmp buffer accessible to the * error_exit routine. To do this, we make a private extension of the * standard JPEG error handler object. (If we were using C++, we'd say we * were making a subclass of the regular error handler.) * * Here's the extended error handler struct: */ struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct my_error_mgr * my_error_ptr; /* * Here's the routine that will replace the standard error_exit method: */ METHODDEF void my_error_exit (j_common_ptr cinfo) { /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ my_error_ptr myerr = (my_error_ptr) cinfo->err; /* Always display the message. */ /* We could postpone this until after returning, if we chose. */ (*cinfo->err->output_message) (cinfo); /* Return control to the setjmp point */ longjmp(myerr->setjmp_buffer, 1); } /* * Sample routine for JPEG decompression. We assume that the source file name * is passed in. We want to return 1 on success, 0 on error. */ GLOBAL int read_JPEG_file (char * filename) { /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ struct jpeg_decompress_struct cinfo; /* We use our private extension JPEG error handler. */ struct my_error_mgr jerr; /* More stuff */ FILE * infile; /* source file */ JSAMPARRAY buffer; /* Output row buffer */ int row_stride; /* physical row width in output buffer */ /* In this example we want to open the input file before doing anything else, * so that the setjmp() error recovery below can assume the file is open. * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that * requires it in order to read binary files. */ if ((infile = fopen(filename, "rb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); return 0; } /* Step 1: allocate and initialize JPEG decompression object */ /* We set up the normal JPEG error routines, then override error_exit. */ cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; /* Establish the setjmp return context for my_error_exit to use. */ if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_decompress(&cinfo); fclose(infile); return 0; } /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); /* Step 2: specify data source (eg, a file) */ jpeg_stdio_src(&cinfo, infile); /* Step 3: read file parameters with jpeg_read_header() */ (void) jpeg_read_header(&cinfo, TRUE); /* We can ignore the return value from jpeg_read_header since * (a) suspension is not possible with the stdio data source, and * (b) we passed TRUE to reject a tables-only JPEG file as an error. * See libjpeg.doc for more info. */ /* Step 4: set parameters for decompression */ /* In this example, we don't need to change any of the defaults set by * jpeg_read_header(), so we do nothing here. */ /* Step 5: Start decompressor */ jpeg_start_decompress(&cinfo); /* We may need to do some setup of our own at this point before reading * the data. After jpeg_start_decompress() we have the correct scaled * output image dimensions available, as well as the output colormap * if we asked for color quantization. * In this example, we need to make an output work buffer of the right size. */ /* JSAMPLEs per row in output buffer */ row_stride = cinfo.output_width * cinfo.output_components; /* Make a one-row-high sample array that will go away when done with image */ buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); /* Step 6: while (scan lines remain to be read) */ /* jpeg_read_scanlines(...); */ /* Here we use the library's state variable cinfo.output_scanline as the * loop counter, so that we don't have to keep track ourselves. */ while (cinfo.output_scanline < cinfo.output_height) { (void) jpeg_read_scanlines(&cinfo, buffer, 1); /* Assume put_scanline_someplace wants a pointer and sample count. */ put_scanline_someplace(buffer[0], row_stride); } /* Step 7: Finish decompression */ (void) jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ /* Step 8: Release JPEG decompression object */ /* This is an important step since it will release a good deal of memory. */ jpeg_destroy_decompress(&cinfo); /* After finish_decompress, we can close the input file. * Here we postpone it until after no more JPEG errors are possible, * so as to simplify the setjmp error logic above. (Actually, I don't * think that jpeg_destroy can do an error exit, but why assume anything...) */ fclose(infile); /* At this point you may want to check to see whether any corrupt-data * warnings occurred (test whether jerr.pub.num_warnings is nonzero). */ /* And we're done! */ return 1; } /* * SOME FINE POINTS: * * In the above code, we ignored the return value of jpeg_read_scanlines, * which is the number of scanlines actually read. We could get away with * this because we asked for only one line at a time and we weren't using * a suspending data source. See libjpeg.doc for more info. * * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); * we should have done it beforehand to ensure that the space would be * counted against the JPEG max_memory setting. In some systems the above * code would risk an out-of-memory error. However, in general we don't * know the output image dimensions before jpeg_start_decompress(), unless we * call jpeg_calc_output_dimensions(). See libjpeg.doc for more about this. * * Scanlines are returned in the same order as they appear in the JPEG file, * which is standardly top-to-bottom. If you must emit data bottom-to-top, * you can use one of the virtual arrays provided by the JPEG memory manager * to invert the data. See wrbmp.c for an example. * * As with compression, some operating modes may require temporary files. * On some systems you may need to set up a signal handler to ensure that * temporary files are deleted if the program is interrupted. See libjpeg.doc. */ \ No newline at end of file diff --git a/Independent JPEG Group/filelist.doc b/Independent JPEG Group/filelist.doc new file mode 100644 index 0000000..73723cc --- /dev/null +++ b/Independent JPEG Group/filelist.doc @@ -0,0 +1 @@ +IJG JPEG LIBRARY: FILE LIST Copyright (C) 1994, Thomas G. Lane. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. Here is a road map to the files in the IJG JPEG distribution. The distribution includes the JPEG library proper, plus two application programs ("cjpeg" and "djpeg") which use the library to convert JPEG files to and from some other popular image formats. THE JPEG LIBRARY ================ Include files: jpeglib.h JPEG library's exported data and function declarations. jconfig.h Configuration declarations. Note: this file is not present in the distribution; it is generated during installation. jmorecfg.h Additional configuration declarations; need not be changed for a standard installation. jerror.h Declares JPEG library's error and trace message codes. jinclude.h Central include file used by library's .c files. jpegint.h JPEG library's internal data structures. jdct.h Private declarations for forward & reverse DCT subsystems. jmemsys.h Private declarations for memory management subsystem. jversion.h Version information. Applications using the library should include jpeglib.h (which in turn includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included if the application needs to reference individual JPEG error codes. The other include files are intended for internal use and would not normally be included by an application program. (cjpeg/djpeg do use jinclude.h, since its function is to improve portability of the whole IJG distribution. Most other applications will directly include the system include files they want, and hence won't need jinclude.h.) C source code files: These files contain most of the functions intended to be called directly by an application program: jcapi.c Application program interface routines for compression. jdapi.c Application program interface routines for decompression. jcomapi.c Application program interface routines common to compression and decompression. jcparam.c Compression parameter setting helper routines. Compression side of the library: jcmaster.c Master control: determines which other modules to use. jcmainct.c Main buffer controller (preprocessor => JPEG compressor). jcprepct.c Preprocessor buffer controller. jccoefct.c Buffer controller for DCT coefficient buffer. jccolor.c Color space conversion. jcsample.c Downsampling. jcdctmgr.c DCT manager (DCT implementation selection & control). jfdctllm.c Forward DCT using LL&M algorithm (very high quality). jchuff.c Huffman entropy coding. jcmarker.c JPEG marker writing. jdatadst.c Data destination manager for stdio output. Decompression side of the library: jdmaster.c Master control: determines which other modules to use. jdmainct.c Main buffer controller (JPEG decompressor => postprocessor). jdcoefct.c Buffer controller for DCT coefficient buffer. jdpostct.c Postprocessor buffer controller. jdmarker.c JPEG marker reading. jdhuff.c Huffman entropy decoding. jddctmgr.c IDCT manager (IDCT implementation selection & control). jidctllm.c Inverse DCT using LL&M algorithm (very high quality). jidctred.c Inverse DCTs with reduced-size outputs. jdsample.c Upsampling. jdcolor.c Color space conversion. jquant1.c One-pass color quantization using a fixed-spacing colormap. jquant2.c Two-pass color quantization using a custom-generated colormap. Also handles one-pass quantization to an externally given map. jdatasrc.c Data source manager for stdio input. Support files for both compression and decompression: jerror.c Standard error handling routines (application replaceable). jmemmgr.c System-independent (more or less) memory management code. jutils.c Miscellaneous utility routines. jmemmgr.c relies on a system-dependent memory management module. The IJG distribution includes the following implementations of the system-dependent module: jmemnobs.c "No backing store": assumes adequate virtual memory exists. jmemansi.c Makes temporary files with ANSI-standard routine tmpfile(). jmemname.c Makes temporary files with program-generated file names. jmemdos.c Custom implementation for MS-DOS: knows about extended and expanded memory as well as temporary files. Exactly one of the system-dependent modules should be configured into an installed JPEG library (see install.doc for hints about which one to use). On unusual systems you may find it worthwhile to make a special system-dependent memory manager. Non-C source code files: jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in MS-DOS-specific configurations of the JPEG library. CJPEG/DJPEG =========== Include files: cdjpeg.h Declarations shared by cjpeg/djpeg modules. cderror.h Additional error and trace message codes for cjpeg/djpeg. C source code files: cjpeg.c Main program for cjpeg. djpeg.c Main program for djpeg. Image file reader modules for cjpeg: rdgif.c GIF file input. rdppm.c PPM/PGM file input. rdtarga.c Targa file input. Image file writer modules for djpeg: wrgif.c GIF file output. wrppm.c PPM/PGM file output. wrtarga.c Targa file output. ADDITIONAL FILES ================ Documentation (see README for a guide to the documentation files): README Master documentation file. *.doc Other documentation files. *.1 Documentation in Unix man page format. change.log Version-to-version change highlights. example.c Sample code for calling JPEG library. Configuration/installation files and programs (see install.doc for more info): configure Unix shell script to perform automatic configuration. ckconfig.c Program to generate jconfig.h on non-Unix systems. jconfig.doc Template for making jconfig.h by hand. makefile.* Sample makefiles for particular systems. jconfig.* Sample jconfig.h for particular systems. ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of L. Peter Deutsch and Aladdin Enterprises). Test files (see install.doc for test procedure): test*.* Source and comparison files for confidence test. These are binary image files, NOT text files. \ No newline at end of file diff --git a/Independent JPEG Group/install.doc b/Independent JPEG Group/install.doc new file mode 100644 index 0000000..a448fe6 --- /dev/null +++ b/Independent JPEG Group/install.doc @@ -0,0 +1 @@ +INSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software Copyright (C) 1991-1994, Thomas G. Lane. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. This file explains how to configure and install the IJG software. We have tried to make this software extremely portable and flexible, so that it can be adapted to almost any environment. The downside of this decision is that the installation process is complicated. We have provided shortcuts to simplify the task on common systems. But in any case, you will need at least a little familiarity with C programming and program build procedures for your system. If you are only using this software as part of a larger program, the larger program's installation procedure may take care of configuring the IJG code. For example, Ghostscript's installation script will configure the IJG code. You don't need to read this file if you just want to compile Ghostscript. In this alpha-test release, the "configure" script is brand new and should not be trusted. Please try it, if you are on a Unix machine; but please also read the hand-installation instructions, and verify that configure produced reasonable Makefile and jconfig.h files. Also, I have not been able to test the canned makefiles and jconfig files for non-Unix machines. Please report any problems to jpeg-info@uunet.uu.net. TABLE OF CONTENTS ----------------- Before you start Configuring the software: using the automatic "configure" script using one of the supplied jconfig and makefile files by hand Building the software Testing the software Installing the software Optional stuff Optimization Hints for specific systems BEFORE YOU START ================ Before installing the software you must unpack the distributed source code. Since you are reading this file, you have probably already succeeded in this task. However, there is a potential for error if you needed to convert the files to the local standard text file format (for example, if you are on MS-DOS you may have converted LF end-of-line to CR/LF). You must apply such conversion to all the files EXCEPT those whose names begin with "test". The test files contain binary data; if you change them in any way then the self-test will give bad results. Please check the last section of this file to see if there are hints for the specific machine or compiler you are using. CONFIGURING THE SOFTWARE ======================== To configure the IJG code for your system, you need to create two files: * jconfig.h: contains values for system-dependent #define symbols. * Makefile: controls the compilation process. (On a non-Unix machine, you may create "project files" or some other substitute for a Makefile. jconfig.h is needed in any environment.) We provide three different ways to generate these files: * On a Unix system, you can just run the "configure" script. * We provide sample jconfig files and makefiles for popular machines; if your machine matches one of the samples, just copy the right sample files to jconfig.h and Makefile. * If all else fails, read the instructions below and make your own files. Configuring the software using the automatic "configure" script --------------------------------------------------------------- If you are on a Unix machine, you can just type ./configure and let the configure script construct appropriate configuration files. If you're using "csh" on an old version of System V, you might need to type sh configure instead to prevent csh from trying to execute configure itself. Expect configure to run for a few minutes, particularly on slower machines; it works by compiling a series of test programs. Configure was created with GNU Autoconf and it follows the usual conventions for GNU configure scripts. It makes a few assumptions that you may want to override. You can do this by providing optional switches to configure: * Configure will use gcc (GNU C compiler) if it's available, otherwise cc. To force a particular compiler to be selected, use the CC option, for example ./configure CC='cc' The same method can be used to include any unusual compiler switches. For example, on HP-UX you probably want to say ./configure CC='cc -Aa' to get HP's compiler to run in ANSI mode. * Configure will set up the makefile so that "make install" will install files into /usr/local/bin, /usr/local/man, etc. You can specify an installation prefix other than "/usr/local" by giving configure the option "--prefix=PATH". * If you don't have a lot of swap space, you may need to enable the IJG software's internal virtual memory mechanism. To do this, give the option "--with-maxmem=N" where N is the default maxmemory limit in megabytes. This is discussed in more detail under "Selecting a memory manager", below. You probably don't need to worry about this on reasonably-sized Unix machines, unless you plan to process very large images. Configure has some other features that are useful if you are cross-compiling or working in a network of multiple machine types; but if you need those features, you probably already know how to use them. Configuring the software using one of the supplied jconfig and makefile files ----------------------------------------------------------------------------- If you have one of these systems, you can just use the provided configuration files: Makefile jconfig file System and/or compiler makefile.manx jconfig.manx Amiga, Manx Aztec C makefile.sas jconfig.sas Amiga, SAS C mak*jpeg.st jconfig.st Atari ST/STE/TT, Pure C or Turbo C makefile.bcc jconfig.bcc MS-DOS, Borland C (Turbo C) makefile.mc6 jconfig.mc6 MS-DOS, Microsoft C version 6.x and up makefile.mms jconfig.vms VAX/VMS, with MMS software makefile.vms jconfig.vms VAX/VMS, without MMS software Copy the proper jconfig file to jconfig.h and the makefile to Makefile, or whatever your system uses as the standard makefile name. (For the Atari, we provide three project files; see the Atari hints below.) [Note to alpha testers: please double-check the contents of these files and report success or failure. Contributions of more system-specific files are welcome.] Configuring the software by hand -------------------------------- First, generate a jconfig.h file. If you are moderately familiar with C, the comments in jconfig.doc should be enough information to do this; just copy jconfig.doc to jconfig.h and edit it appropriately. Otherwise, you may prefer to use the ckconfig.c program. You will need to compile and execute ckconfig.c by hand --- we hope you know at least enough to do that. ckconfig.c may not compile the first try (in fact, the whole idea is for it to fail if anything is going to). If you get compile errors, fix them by editing ckconfig.c according to the directions given in ckconfig.c. Once you get it to run, it will write a suitable jconfig.h file, and will also print out some advice about which makefile to use. You may also want to look at the canned jconfig files, if there is one for a system similar to yours. Second, select a makefile and copy it to Makefile (or whatever your system uses as the standard makefile name). The most generic makefiles we provide are makefile.ansi: if your C compiler supports function prototypes makefile.unix: if not. (You have function prototypes if ckconfig.c put "#define HAVE_PROTOTYPES" in jconfig.h.) You may want to start from one of the other makefiles if there is one for a system similar to yours. Look over the selected Makefile and adjust options as needed. In particular you may want to change the CC and CFLAGS definitions. For instance, if you are using GCC, set CC=gcc. If you had to use any compiler switches to get ckconfig.c to work, make sure the same switches are in CFLAGS. If you are on a system that doesn't use makefiles, you'll need to set up project files (or whatever you do use) to compile all the source files and link them into executable files cjpeg and djpeg. See the file lists in any of the makefiles to find out which files go into each program. Note that the provided makefiles all make a "library" file libjpeg first, but you don't have to do that if you don't want to; the file lists identify which source files are actually needed for compression, decompression, or both. As a last resort, you can make a batch script that just compiles everything and links it all together; makefile.vms is an example of this (it's for VMS systems that have no make-like utility). Here are comments about some specific configuration decisions you'll need to make: Command line style ------------------ cjpeg and djpeg can use a Unix-like command line style which supports redirection and piping, like this: cjpeg inputfile >outputfile cjpeg outputfile source program | cjpeg >outputfile The simpler "two file" command line style is just cjpeg inputfile outputfile You may prefer the two-file style, particularly if you don't have pipes. You MUST use two-file style on any system that doesn't cope well with binary data fed through stdin/stdout; this is true for most MS-DOS compilers, for example. If you're not on a Unix system, it's safest to assume you need two-file style. (But if your compiler provides either the Posix-standard fdopen() library routine or a Microsoft-compatible setmode() routine, you can use the Unix command line style, by defining USE_FDOPEN or USE_SETMODE respectively.) To use the two-file style, make jconfig.h say "#define TWO_FILE_COMMANDLINE". Selecting a memory manager -------------------------- The IJG code is capable of working on images that are too big to fit in main memory; data is swapped out to temporary files as necessary. However, the code to do this is rather system-dependent. We provide four different memory managers: * jmemansi.c This version uses the ANSI-standard library routine tmpfile(), which not all non-ANSI systems have. On some systems tmpfile() may put the temporary file in a non-optimal location; if you don't like what it does, use jmemname.c. * jmemname.c This version creates named temporary files. For anything except a Unix machine, you'll need to configure the select_file_name() routine appropriately; see the comments near the head of jmemname.c. If you use this version, define NEED_SIGNAL_CATCHER in jconfig.h to make sure the temp files are removed if the program is aborted. * jmemnobs.c (That stands for No Backing Store :-).) This will compile on almost any system, but it assumes you have enough main memory or virtual memory to hold the biggest images you work with. * jmemdos.c This should be used in most MS-DOS installations; see the system-specific notes about MS-DOS for more info. IMPORTANT: if you use this, define USE_MSDOS_MEMMGR in jconfig.h, and include the assembly file jmemdosa.asm in the programs. The supplied makefiles and jconfig files for MS-DOS compilers already do both. To use a particular memory manager, change the SYSDEPMEM variable in your makefile to equal the corresponding object file name (for example, jmemansi.o or jmemansi.obj for jmemansi.c). If you have plenty of (real or virtual) main memory, just use jmemnobs.c. "Plenty" means about ten bytes for every pixel in the largest images you plan to process, so a lot of systems don't meet this criterion. If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have to use jmemname.c; be sure to adjust select_file_name() for local conditions. You may also need to change unlink() to remove() in close_backing_store(). Except with jmemnobs.c, you need to adjust the DEFAULT_MAX_MEM setting to a reasonable value for your system (either by adding a #define for DEFAULT_MAX_MEM to jconfig.h, or by adding a -D switch to the Makefile). This value limits the amount of data space the program will attempt to allocate. Code and static data space isn't counted, so the actual memory needs for cjpeg or djpeg are typically 100 to 150Kb more than the max-memory setting. Larger max-memory settings reduce the amount of I/O needed to process a large image, but too large a value can result in "insufficient memory" failures. On most Unix machines (and other systems with virtual memory), just set DEFAULT_MAX_MEM to several million and forget it. At the other end of the spectrum, for MS-DOS machines you probably can't go much above 300K to 400K. (On MS-DOS the value refers to conventional memory; extended/expanded memory is handled separately by jmemdos.c.) BUILDING THE SOFTWARE ===================== Now you should be able to compile the software. Just say "make" (or whatever's necessary to start the compilation). Have a cup of coffee. Here are some things that could go wrong: If your compiler complains about undefined structures, you should be able to shut it up by putting "#define INCOMPLETE_TYPES_BROKEN" in jconfig.h. If you have trouble with missing system include files or inclusion of the wrong ones, read jinclude.h. This shouldn't happen if you used configure or ckconfig.c to set up jconfig.h. If you don't have a getenv() library routine, define NO_GETENV. There are a fair number of routines that do not use all of their parameters; some compilers will issue warnings about this, which you can ignore. Any other warning deserves investigation. Also see the system-specific hints, below. TESTING THE SOFTWARE ==================== As a quick test of functionality we've included a small sample image in several forms: testorig.jpg A reduced section of the well-known Lenna picture. testimg.ppm The output of djpeg testorig.jpg testimg.gif The output of djpeg -gif testorig.jpg testimg.jpg The output of cjpeg testimg.ppm (The two .jpg files aren't identical since JPEG is lossy.) If you can generate duplicates of the testimg.* files then you probably have working programs. With most of the makefiles, "make test" will perform the necessary comparisons. If you're using a makefile that doesn't provide the test option, run djpeg and cjpeg by hand to generate testout.ppm, testout.gif, and testout.jpg, then compare these to testimg.* with whatever binary file comparison tool you have. The files should be bit-for-bit identical. If the cjpeg test run fails with "Missing Huffman code table entry", it's a good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to the configuration step and run ckconfig.c. (This is a good plan for any other test failure, too.) If you are using Unix (one-file) command line style on a non-Unix system, it's a good idea to check that binary I/O through stdin/stdout actually works. You should get the same results from "djpeg out.ppm" as from "djpeg -outfile out.ppm testorig.jpg". Note that the makefiles all use the latter style and therefore do not exercise stdin/stdout! If this check fails, try recompiling cjpeg.c and djpeg.c with USE_SETMODE or USE_FDOPEN. If it still doesn't work, better use two-file style. If you chose a memory manager other than jmemnobs.c, you should test that temporary-file usage works. Try "djpeg -gif -max 0 testorig.jpg" and make sure its output matches testimg.gif. If you have any really large images handy, try compressing them with -optimize and/or decompressing with -gif to make sure your DEFAULT_MAX_MEM setting is not too large. NOTE: this is far from an exhaustive test of the JPEG software; some modules, such as 1-pass color quantization, are not exercised at all. It's just a quick test to give you some confidence that you haven't missed something major. INSTALLING THE SOFTWARE ======================= Once you're done with the above steps, you can install the software by copying the executable files (cjpeg and djpeg) to wherever you normally install programs. On Unix systems, you'll also want to put cjpeg.1 and djpeg.1 in the man-page directory. The canned makefiles don't support this step since there's such a wide variety of installation procedures on different systems. If you generated a Makefile with the "configure" script, you can just say make install to install the cjpeg and djpeg programs and their man pages into the standard places. (You'll probably need to be root to do this.) We recommend first saying make -n install to see where configure thought the files should go. You may need to edit the Makefile, particularly if your system's conventions for man page filenames don't match what configure expects. If you want to install the library file libjpeg.a and the include files j*.h (for use in compiling other programs besides cjpeg/djpeg), then say make install-lib OPTIONAL STUFF ============== Progress monitor: If you like, you can #define PROGRESS_REPORT (in jconfig.h) to enable display of percent-done progress reports. The routines provided in cjpeg.c/djpeg.c merely print percentages to stderr, but you can customize them to do something fancier. Utah RLE file format support: We distribute the software with support for RLE image files (Utah Raster Toolkit format) disabled, because the RLE support won't compile without the Utah library. If you have URT version 3.0, you can enable RLE support as follows: 1. #define RLE_SUPPORTED in jconfig.h. 2. Add a -I option to CFLAGS in the Makefile for the directory containing the URT .h files (typically the "include" subdirectory of the URT distribution). 3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies the directory containing the URT "librle.a" file (typically the "lib" subdirectory of the URT distribution). [Note: RLE support is not currently present in v5. Any volunteers to make it work again?] Removing code: If you need to make a smaller version of the JPEG software, some optional functions can be removed at compile time. See the xxx_SUPPORTED #defines in jconfig.h and jmorecfg.h. If at all possible, we recommend that you leave in decoder support for all valid JPEG files, to ensure that you can read anyone's output. Taking out support for image file formats that you don't use is the most painless way to make the programs smaller. OPTIMIZATION ============ Unless you own a Cray, you'll probably be interested in making the JPEG software go as fast as possible. This section covers some machine-dependent optimizations you may want to try. We suggest that before trying any of this, you first get the basic installation to pass the self-test step. Repeat the self-test after any optimization to make sure that you haven't broken anything. The JPEG DCT routines perform a lot of multiplications. These multiplications must yield 32-bit results, but none of their input values are more than 16 bits wide. On many machines, notably the 680x0 and 80x86 CPUs, a 16x16=>32 bit multiply instruction is faster than a full 32x32=>32 bit multiply. Unfortunately there is no portable way to specify such a multiplication in C, but some compilers can generate one when you use the right combination of casts. See the MULTIPLY macro definitions in jfwddct.c and jrevdct.c. If your compiler makes "int" be 32 bits and "short" be 16 bits, defining SHORTxSHORT_32 is fairly likely to work. When experimenting with alternate definitions, be sure to test not only whether the code still works (use the self-test), but also whether it is actually faster --- on some compilers, alternate definitions may compute the right answer, yet be slower than the default. Timing cjpeg on a large PPM input file is the best way to check this, as the DCT will be the largest fraction of the runtime in that mode. (Note: some of the distributed compiler-specific jconfig files already contain #define switches to select an appropriate MULTIPLY definition.) If access to "short" arrays is slow on your machine, it may be a win to define type JCOEF as int rather than short. This will cost a good deal of memory though, particularly in some multi-pass modes, so don't do it unless you have memory to burn and short is REALLY slow. If your compiler can compile function calls in-line, make sure the INLINE macro in jmorecfg.h is defined as the keyword that marks a function inline-able. Some compilers have a switch that tells the compiler to inline any function it thinks is profitable (e.g., -finline-functions for gcc). Enabling such a switch is likely to make the compiled code bigger but faster. In general, it's worth trying the maximum optimization level of your compiler, and experimenting with any optional optimizations such as loop unrolling. (Unfortunately, far too many compilers have optimizer bugs ... be prepared to back off if the code fails self-test.) If you do any experimentation along these lines, please report the optimal settings to jpeg-info@uunet.uu.net so we can mention them in future releases. Be sure to specify your machine and compiler version. HINTS FOR SPECIFIC SYSTEMS ========================== We welcome reports on changes needed for systems not mentioned here. Submit 'em to jpeg-info@uunet.uu.net. Also, if configure or ckconfig.c is wrong about how to configure the JPEG software for your system, please let us know. Amiga: SAS C 6.50 reportedly is too buggy to compile the IJG code properly. A patch to update to 6.51 is available from SAS or AmiNet FTP sites. Atari: Copy the project files makcjpeg.st, makdjpeg.st, and makljpeg.st to cjpeg.prj, djpeg.prj, and libjpeg.prj respectively. The project files should work as-is with Pure C. For Turbo C, change library filenames "PC..." to "TC..." in cjpeg.prj and djpeg.prj. Note that libjpeg.prj selects jmemansi.c as the recommended memory manager. You'll probably want to adjust the DEFAULT_MAX_MEM setting --- you want it to be a couple hundred K less than your normal free memory. Put "#define DEFAULT_MAX_MEM nnnn" into jconfig.h to do this. Note that you must make libjpeg.lib before making cjpeg.ttp or djpeg.ttp. You'll have to perform the self-test by hand. There is a bug in some older versions of the Turbo C library which causes the space used by temporary files created with "tmpfile()" not to be freed after an abnormal program exit. If you check your disk afterwards, you will find cluster chains that are allocated but not used by a file. This should not happen in cjpeg or djpeg, since we enable a signal catcher to explicitly close temp files before exiting. But if you use the JPEG library with your own code, be sure to supply a signal catcher, or else use a different system-dependent memory manager. Cray: Should you be so fortunate as to be running JPEG on a Cray YMP, there is a compiler bug in Cray's Standard C versions prior to 3.1. You'll need to insert a line reading "#pragma novector" just before the loop for (i = 1; i <= (int) htbl->bits[l]; i++) huffsize[p++] = (char) l; in fix_huff_tbl (in V4A, line 42 of jchuff.c and line 39 of jdhuff.c). The usual symptom of not adding this line is a core-dump. See Cray's SPR 48222. [This bug may or may not still occur with V5; can anyone test it?] HP-UX: If you have HP-UX 7.05 or later with the "software development" C compiler, you should run the compiler in ANSI mode. If using the configure script, say ./configure CC='cc -Aa' (or -Ae if you prefer). If configuring by hand, use makefile.ansi and add "-Aa" to the CFLAGS line in the makefile. If you have a pre-7.05 system, or if you are using the non-ANSI C compiler delivered with a minimum HP-UX system, then you must use makefile.unix (and do NOT add -Aa); or just run configure without the CC option. On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior to A.08.07. If you get complaints about "not a typedef name", you'll have to use makefile.unix, or run configure without the CC option. Macintosh MPW: We don't directly support MPW in the current release, but Larry Rosenstein ported an earlier version of the IJG code without very much trouble. There's useful notes and conversion scripts in his kit for porting PBMPLUS to MPW. You can obtain the kit by FTP to ftp.apple.com, file /pub/lsr/pbmplus-port*. Macintosh Think C: The supplied user-interface files (cjpeg.c and djpeg.c) are set up to provide a Unix-style command line interface. You can use this interface on the Mac by means of Think's ccommand() library routine. However, a much better Mac-style user interface has been prepared by Jim Brunner. You can obtain the additional source code needed for that user interface by FTP to sumex-aim.stanford.edu, file /info-mac/source/c/jpeg-convert.hqx. Jim's documentation also includes more detailed build instructions for Think C. [I hope someone will update JPEG Convert to work with V5...] If you want to build the minimal command line version, proceed as follows: You'll have to prepare project files for cjpeg and djpeg; we don't include those in the distribution since they are not text files. Use the file lists in any of the supplied makefiles as a guide. Also add the ANSI and Unix C libraries in a separate segment. You may need to divide the JPEG files into more than one segment; we recommend dividing compression and decompression modules. MIPS R3000: MIPS's cc version 1.31 has a rather nasty optimization bug. Don't use -O if you have that compiler version. (Use "cc -V" to check the version.) Note that the R3000 chip is found in workstations from DEC and others. MS-DOS, generic comments: The JPEG code is designed to be compiled with 80x86 "small" or "medium" memory models (i.e., data pointers are 16 bits unless explicitly declared "far"; code pointers can be either size). You should be able to use small model to compile cjpeg or djpeg by itself, but you will probably have to go to medium model if you include the JPEG code in a larger application. This shouldn't hurt performance much. You *will* take a noticeable performance hit if you compile in a large-data memory model, and you should avoid "huge" model if at all possible. Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use a small-data model; be sure it is NOT defined if you use a large-data memory model. (It is defined in the supplied jconfig files for Borland and Microsoft C.) The DOS-specific memory manager, jmemdos.c, should be used if possible. It needs some assembly-code routines which are in jmemdosa.asm; make sure your makefile assembles that file and includes it in the library. When using jmemdos.c, jconfig.h must define USE_MSDOS_MEMMGR and must set MAX_ALLOC_CHUNK to less than 64K (65520L is a typical value). If you can't use jmemdos.c for some reason --- for example, because you don't have a Microsoft-compatible assembler to assemble jmemdosa.asm --- you'll have to fall back to jmemansi.c or jmemname.c. You'll probably still need to set MAX_ALLOC_CHUNK in jconfig.h, because most DOS C libraries won't malloc() more than 64K at a time. IMPORTANT: if you use jmemansi.c or jmemname.c, you will have to compile in a large-data memory model in order to get the right stdio library. Too bad. None of the above advice applies if you are using a 386 flat-memory-space environment, such as DJGPP or Watcom C. (And you should use one if you have it, as performance will be much better than 8086-compatible code!) For flat-memory-space compilers, do NOT define NEED_FAR_POINTERS, and do NOT use jmemdos.c. Use jmemnobs.c if the environment supplies adequate virtual memory, otherwise use jmemansi.c or jmemname.c. Most MS-DOS compilers treat stdin/stdout as text files, so you must use two-file command line style. But if your compiler has either fdopen() or setmode(), you can use one-file style if you like. To do this, define USE_FDOPEN or USE_SETMODE so that stdin/stdout will be set to binary mode. (USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You should test that I/O through stdin/stdout produces the same results as I/O to explicitly named files... the "make test" procedures in the supplied makefiles do NOT use stdin/stdout. MS-DOS, Borland C: Be sure to convert all the source files to DOS text format (CR/LF newlines). Although Borland C will often work OK with unmodified Unix (LF newlines) source files, sometimes it will give bogus compile errors. "Illegal character '#'" is the most common such error. If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. jconfig.bcc includes #define USE_SETMODE. (fdopen does not work correctly.) MS-DOS, DJGPP: Use makefile.ansi and jmemnobs.c. Define either USE_SETMODE or TWO_FILE_COMMANDLINE in jconfig.h, depending on whether you prefer one-file or two-file command line style. You'll need to put the object-file lists into response files in order to circumvent DOS's 128-byte command line length limit at the final linking step. [There should probably be a set of canned config files for DJGPP. Any volunteers?] MS-DOS, Microsoft C: Old versions of MS C fail with an "out of macro expansion space" error because they can't cope with the macro TRACEMS8 (defined in jerror.h). If this happens to you, the easiest solution is to change TRACEMS8 to expand to nothing. You'll lose the ability to dump out JPEG coefficient tables with djpeg -debug -debug, but at least you can compile. Original MS C 6.0 is very buggy; it compiles incorrect code unless you turn off optimization entirely (remove -O from CFLAGS). 6.00A is better, but it still generates bad code if you enable loop optimizations (-Ol or -Ox). If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE. jconfig.mc6 includes #define USE_SETMODE. (fdopen does not work correctly.) SGI: Set "AR2= ar -ts" rather than "AR2= ranlib" in the Makefile. If you are using configure, you should say ./configure RANLIB='ar -ts' \ No newline at end of file diff --git a/Independent JPEG Group/jcapi.c b/Independent JPEG Group/jcapi.c new file mode 100644 index 0000000..9ec737c --- /dev/null +++ b/Independent JPEG Group/jcapi.c @@ -0,0 +1 @@ +/* * jcapi.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the compression half of * the JPEG library. Most of the routines intended to be called directly by * an application are in this file. But also see jcparam.c for * parameter-setup helper routines, and jcomapi.c for routines shared by * compression and decompression. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Initialization of a JPEG compression object. * The error manager must already be set up (in case memory manager fails). */ GLOBAL void jpeg_create_compress (j_compress_ptr cinfo) { int i; /* For debugging purposes, zero the whole master structure. * But error manager pointer is already there, so save and restore it. */ { struct jpeg_error_mgr * err = cinfo->err; MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); cinfo->err = err; } cinfo->is_decompressor = FALSE; /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->dest = NULL; cinfo->comp_info = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } cinfo->input_gamma = 1.0; /* in case application forgets */ /* OK, I'm ready */ cinfo->global_state = CSTATE_START; } /* * Destruction of a JPEG compression object */ GLOBAL void jpeg_destroy_compress (j_compress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } /* * Forcibly suppress or un-suppress all quantization and Huffman tables. * Marks all currently defined tables as already written (if suppress) * or not written (if !suppress). This will control whether they get emitted * by a subsequent jpeg_start_compress call. * * This routine is exported for use by applications that want to produce * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but * since it is called by jpeg_start_compress, we put it here --- otherwise * jcparam.o would be linked whether the application used it or not. */ GLOBAL void jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) { int i; JQUANT_TBL * qtbl; JHUFF_TBL * htbl; for (i = 0; i < NUM_QUANT_TBLS; i++) { if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) qtbl->sent_table = suppress; } for (i = 0; i < NUM_HUFF_TBLS; i++) { if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) htbl->sent_table = suppress; if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) htbl->sent_table = suppress; } } /* * Compression initialization. * Before calling this, all parameters and a data destination must be set up. * * We require a write_all_tables parameter as a failsafe check when writing * multiple datastreams from the same compression object. Since prior runs * will have left all the tables marked sent_table=TRUE, a subsequent run * would emit an abbreviated stream (no tables) by default. This may be what * is wanted, but for safety's sake it should not be the default behavior: * programmers should have to make a deliberate choice to emit abbreviated * images. Therefore the documentation and examples should encourage people * to pass write_all_tables=TRUE; then it will take active thought to do the * wrong thing. */ GLOBAL void jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (write_all_tables) jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */ /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Perform master selection of active modules */ jinit_master_compress(cinfo); /* Set up for the first pass */ (*cinfo->master->prepare_for_pass) (cinfo); /* Ready for application to drive first pass through jpeg_write_scanlines */ cinfo->next_scanline = 0; cinfo->global_state = CSTATE_SCANNING; } /* * Write some scanlines of data to the JPEG compressor. * * The return value will be the number of lines actually written. * This should be less than the supplied num_lines only in case that * the data destination module has requested suspension of the compressor, * or if more than image_height scanlines are passed in. */ GLOBAL JDIMENSION jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines) { JDIMENSION row_ctr, rows_left; if (cinfo->global_state != CSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Give master control module another chance if this is first call to * jpeg_write_scanlines. This lets output of the frame/scan headers be * delayed so that application can write COM, etc, markers between * jpeg_start_compress and jpeg_write_scanlines. */ if (cinfo->master->call_pass_startup) (*cinfo->master->pass_startup) (cinfo); /* Ignore any extra scanlines at bottom of image. */ rows_left = cinfo->image_height - cinfo->next_scanline; if (num_lines > rows_left) num_lines = rows_left; row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); cinfo->next_scanline += row_ctr; return row_ctr; } /* * Finish JPEG compression. * * If a multipass operating mode was selected, this may do a great deal of * work including most of the actual output. */ GLOBAL void jpeg_finish_compress (j_compress_ptr cinfo) { if (cinfo->global_state != CSTATE_SCANNING || cinfo->next_scanline != cinfo->image_height) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Terminate first pass */ (*cinfo->master->finish_pass) (cinfo); /* Perform any remaining passes */ while (! cinfo->master->is_last_pass) { (*cinfo->master->prepare_for_pass) (cinfo); cinfo->next_scanline = 0; while (cinfo->next_scanline < cinfo->image_height) { (*cinfo->main->process_data) (cinfo, NULL, &cinfo->next_scanline, 0); } (*cinfo->master->finish_pass) (cinfo); } /* Write EOI, do final cleanup */ (*cinfo->marker->write_file_trailer) (cinfo); (*cinfo->dest->term_destination) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); } /* * Alternate compression function: just write an abbreviated table file. * Before calling this, all parameters and a data destination must be set up. * * To produce a pair of files containing abbreviated tables and abbreviated * image data, one would proceed as follows: * * initialize JPEG object * set JPEG parameters * set destination to table file * jpeg_write_tables(cinfo); * set destination to image file * jpeg_start_compress(cinfo, FALSE); * write data... * jpeg_finish_compress(cinfo); * * jpeg_write_tables has the side effect of marking all tables written * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress * will not re-emit the tables unless it is passed write_all_tables=TRUE. */ GLOBAL void jpeg_write_tables (j_compress_ptr cinfo) { if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* (Re)initialize error mgr and destination modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->dest->init_destination) (cinfo); /* Initialize the marker writer ... bit of a crock to do it here. */ jinit_marker_writer(cinfo); /* Write them tables! */ (*cinfo->marker->write_tables_only) (cinfo); /* And clean up. */ (*cinfo->dest->term_destination) (cinfo); /* We can use jpeg_abort to release memory ... is this necessary? */ jpeg_abort((j_common_ptr) cinfo); } /* * Abort processing of a JPEG compression operation, * but don't destroy the object itself. */ GLOBAL void jpeg_abort_compress (j_compress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } \ No newline at end of file diff --git a/Independent JPEG Group/jccoefct.c b/Independent JPEG Group/jccoefct.c new file mode 100644 index 0000000..754e3a5 --- /dev/null +++ b/Independent JPEG Group/jccoefct.c @@ -0,0 +1 @@ +/* * jccoefct.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the coefficient buffer controller for compression. * This controller is the top level of the JPEG compressor proper. * The coefficient buffer lies between forward-DCT and entropy encoding steps. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private buffer controller object */ typedef struct { struct jpeg_c_coef_controller pub; /* public fields */ JDIMENSION MCU_row_num; /* keep track of MCU row # within image */ /* When not doing entropy optimization, it's sufficient to buffer just * one MCU (although this may prove a bit slow in practice). We allocate a * workspace of MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each * MCU constructed and sent. On 80x86, the workspace is FAR even though * it's not really very big; this is to keep the module interfaces unchanged * when a large coefficient buffer is necessary. */ JBLOCKROW MCU_buffer[MAX_BLOCKS_IN_MCU]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; /* * Initialize for a processing pass. */ METHODDEF void start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; switch (pass_mode) { case JBUF_PASS_THRU: break; default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } coef->MCU_row_num = 0; } /* * Process some data. * * NB: input_buf contains a plane for each component in scan. */ METHODDEF void compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_MCU_row = cinfo->MCU_rows_in_scan - 1; int blkn, bi, ci, yindex, blockcnt; JDIMENSION ypos, xpos; jpeg_component_info *compptr; /* Loop to write as much as one whole MCU row */ for (MCU_col_num = *in_mcu_ctr; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Determine where data comes from in input_buf and do the DCT thing. * Each call on forward_DCT processes a horizontal row of DCT blocks * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks * sequentially. Dummy blocks at the right or bottom edge are filled in * specially. The data in them does not matter for image reconstruction, * so we fill them with values that will encode to the smallest amount of * data, viz: all zeroes in the AC entries, DC entries equal to previous * block's DC value. (Thanks to Thomas Kinsman for this idea.) */ blkn = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; if (MCU_col_num < last_MCU_col) blockcnt = compptr->MCU_width; else blockcnt = compptr->last_col_width; xpos = MCU_col_num * compptr->MCU_sample_width; ypos = 0; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->MCU_row_num < last_MCU_row || yindex < compptr->last_row_height) { (*cinfo->fdct->forward_DCT) (cinfo, compptr, input_buf[ci], coef->MCU_buffer[blkn], ypos, xpos, (JDIMENSION) blockcnt); if (blockcnt < compptr->MCU_width) { /* Create some dummy blocks at the right edge of the image. */ jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); for (bi = blockcnt; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; } } } else { /* Create a whole row of dummy blocks at the bottom of the image. */ jzero_far((void FAR *) coef->MCU_buffer[blkn], compptr->MCU_width * SIZEOF(JBLOCK)); for (bi = 0; bi < compptr->MCU_width; bi++) { coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; } } blkn += compptr->MCU_width; ypos += DCTSIZE; } } /* Try to write the MCU. In event of a suspension failure, we will * re-DCT the MCU on restart (a bit inefficient, could be fixed...) */ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) break; /* suspension forced; exit loop */ } if (MCU_col_num > last_MCU_col) coef->MCU_row_num++; /* advance if we finished the row */ *in_mcu_ctr = MCU_col_num; } /* * Initialize coefficient buffer controller. */ GLOBAL void jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; JBLOCKROW buffer; int i; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_c_coef_controller *) coef; coef->pub.start_pass = start_pass; coef->pub.compress_data = compress_data; /* Create the coefficient buffer. */ if (need_full_buffer) { ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); } else { buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } } } \ No newline at end of file diff --git a/Independent JPEG Group/jccolor.c b/Independent JPEG Group/jccolor.c new file mode 100644 index 0000000..fe3de08 --- /dev/null +++ b/Independent JPEG Group/jccolor.c @@ -0,0 +1 @@ +/* * jccolor.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains input colorspace conversion routines. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private subobject */ typedef struct { struct jpeg_color_converter pub; /* public fields */ /* Private state for RGB->YCC conversion */ INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */ } my_color_converter; typedef my_color_converter * my_cconvert_ptr; /**************** RGB -> YCbCr conversion: most common case **************/ /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + MAXJSAMPLE/2 * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + MAXJSAMPLE/2 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times R,G,B for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. * The MAXJSAMPLE/2 offsets and the rounding fudge-factor of 0.5 are included * in the tables to save adding them separately in the inner loop. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L< Y section */ #define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */ #define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */ #define R_CB_OFF (3*(MAXJSAMPLE+1)) #define G_CB_OFF (4*(MAXJSAMPLE+1)) #define B_CB_OFF (5*(MAXJSAMPLE+1)) #define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */ #define G_CR_OFF (6*(MAXJSAMPLE+1)) #define B_CR_OFF (7*(MAXJSAMPLE+1)) #define TABLE_SIZE (8*(MAXJSAMPLE+1)) /* * Initialize for RGB->YCC colorspace conversion. */ METHODDEF void rgb_ycc_start (j_compress_ptr cinfo) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; INT32 * rgb_ycc_tab; INT32 i; /* Allocate and fill in the conversion tables. */ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (TABLE_SIZE * SIZEOF(INT32))); for (i = 0; i <= MAXJSAMPLE; i++) { rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF; rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1); /* B=>Cb and R=>Cr tables are the same rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + ONE_HALF*(MAXJSAMPLE+1); */ rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; } } /* * Convert some rows of samples to the JPEG colorspace. * * Note that we change from the application's interleaved-pixel format * to our internal noninterleaved, one-plane-per-component format. * The input buffer is therefore three times as wide as the output buffer. * * A starting row offset is provided only for the output buffer. The caller * can easily adjust the passed input_buf value to accommodate any row * offset required on that side. */ METHODDEF void rgb_ycc_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr[0]); g = GETJSAMPLE(inptr[1]); b = GETJSAMPLE(inptr[2]); inptr += 3; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); } } } /**************** Cases other than RGB -> YCbCr **************/ /* * Convert some rows of samples to the JPEG colorspace. * This version handles RGB->grayscale conversion, which is the same * as the RGB->Y portion of RGB->YCbCr. * We assume rgb_ycc_start has been called (we only use the Y tables). */ METHODDEF void rgb_gray_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr = output_buf[0][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = GETJSAMPLE(inptr[0]); g = GETJSAMPLE(inptr[1]); b = GETJSAMPLE(inptr[2]); inptr += 3; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles Adobe-style CMYK->YCCK conversion, * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same * conversion as above, while passing K (black) unchanged. * We assume rgb_ycc_start has been called. */ METHODDEF void cmyk_ycck_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int r, g, b; register INT32 * ctab = cconvert->rgb_ycc_tab; register JSAMPROW inptr; register JSAMPROW outptr0, outptr1, outptr2, outptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { inptr = *input_buf++; outptr0 = output_buf[0][output_row]; outptr1 = output_buf[1][output_row]; outptr2 = output_buf[2][output_row]; outptr3 = output_buf[3][output_row]; output_row++; for (col = 0; col < num_cols; col++) { r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); /* K passes through as-is */ outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */ inptr += 4; /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations * must be too; we do not need an explicit range-limiting operation. * Hence the value being shifted is never negative, and we don't * need the general RIGHT_SHIFT macro. */ /* Y */ outptr0[col] = (JSAMPLE) ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS); /* Cb */ outptr1[col] = (JSAMPLE) ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) >> SCALEBITS); /* Cr */ outptr2[col] = (JSAMPLE) ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) >> SCALEBITS); } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles grayscale output with no conversion. * The source can be either plain grayscale or YCbCr (since Y == gray). */ METHODDEF void grayscale_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; JDIMENSION num_cols = cinfo->image_width; int instride = cinfo->input_components; while (--num_rows >= 0) { inptr = *input_buf++; outptr = output_buf[0][output_row]; output_row++; for (col = 0; col < num_cols; col++) { outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */ inptr += instride; } } } /* * Convert some rows of samples to the JPEG colorspace. * This version handles multi-component colorspaces without conversion. * We assume input_components == num_components. */ METHODDEF void null_convert (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows) { register JSAMPROW inptr; register JSAMPROW outptr; register JDIMENSION col; register int ci; int nc = cinfo->num_components; JDIMENSION num_cols = cinfo->image_width; while (--num_rows >= 0) { /* It seems fastest to make a separate pass for each component. */ for (ci = 0; ci < nc; ci++) { inptr = *input_buf; outptr = output_buf[ci][output_row]; for (col = 0; col < num_cols; col++) { outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ inptr += nc; } } input_buf++; output_row++; } } /* * Empty method for start_pass. */ METHODDEF void null_method (j_compress_ptr cinfo) { /* no work needed */ } /* * Module initialization routine for input colorspace conversion. */ GLOBAL void jinit_color_converter (j_compress_ptr cinfo) { my_cconvert_ptr cconvert; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_converter)); cinfo->cconvert = (struct jpeg_color_converter *) cconvert; /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; /* Make sure input_components agrees with in_color_space */ switch (cinfo->in_color_space) { case JCS_GRAYSCALE: if (cinfo->input_components != 1) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; case JCS_RGB: case JCS_YCbCr: if (cinfo->input_components != 3) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->input_components != 4) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->input_components < 1) ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); break; } /* Check num_components, set conversion method based on requested space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_GRAYSCALE) cconvert->pub.color_convert = grayscale_convert; else if (cinfo->in_color_space == JCS_RGB) { cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_gray_convert; } else if (cinfo->in_color_space == JCS_YCbCr) cconvert->pub.color_convert = grayscale_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_RGB) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_RGB) { cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = rgb_ycc_convert; } else if (cinfo->in_color_space == JCS_YCbCr) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); if (cinfo->in_color_space == JCS_CMYK) { cconvert->pub.start_pass = rgb_ycc_start; cconvert->pub.color_convert = cmyk_ycck_convert; } else if (cinfo->in_color_space == JCS_YCCK) cconvert->pub.color_convert = null_convert; else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; default: /* allow null conversion of JCS_UNKNOWN */ if (cinfo->jpeg_color_space != cinfo->in_color_space || cinfo->num_components != cinfo->input_components) ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); cconvert->pub.color_convert = null_convert; break; } } \ No newline at end of file diff --git a/Independent JPEG Group/jcdctmgr.c b/Independent JPEG Group/jcdctmgr.c new file mode 100644 index 0000000..d98125a --- /dev/null +++ b/Independent JPEG Group/jcdctmgr.c @@ -0,0 +1 @@ +/* * jcdctmgr.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the forward-DCT management logic. * This code selects a particular DCT implementation to be used, * and it performs related housekeeping chores including coefficient * quantization. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* Private subobject for this module */ typedef struct { struct jpeg_forward_dct pub; /* public fields */ /* no private fields for now */ } my_fdct_controller; typedef my_fdct_controller * my_fdct_ptr; /* ZAG[i] is the natural-order position of the i'th element of zigzag order. */ static const int ZAG[DCTSIZE2] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; /* * Initialize for a processing pass. * Verify that all referenced Q-tables are present, and set up * the multiplier tables for each one. */ METHODDEF void start_pass (j_compress_ptr cinfo) { int ci, qtblno, i; JCQUANT_TBL * qtbl; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { qtblno = cinfo->cur_comp_info[ci]->quant_tbl_no; /* Make sure specified quantization table is present */ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); /* Compute divisors for this quant table */ /* We may do this more than once for same table, but it's not a big deal */ qtbl = (JCQUANT_TBL *) cinfo->quant_tbl_ptrs[qtblno]; for (i = 0; i < DCTSIZE2; i++) { /* For now, divisors are same as raw quantization coefficients */ qtbl->divisors[i] = (MULTIPLIER) qtbl->pub.quantval[i]; } } } /* * Perform forward DCT on one or more blocks of a component. * * The input samples are taken from the sample_data[] array starting at * position start_row/start_col, and moving to the right for any additional * blocks. The quantized, zigzagged coefficients are returned in coef_blocks[]. */ METHODDEF void forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks) { /* This routine is heavily used, so it's worth coding it tightly. */ int workspace[DCTSIZE2]; /* work area for FDCT subroutine */ JDIMENSION bi; JCQUANT_TBL * qtbl; qtbl = (JCQUANT_TBL *) cinfo->quant_tbl_ptrs[compptr->quant_tbl_no]; sample_data += start_row; /* fold in the vertical offset once */ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { { register int *workspaceptr; register JSAMPROW elemptr; register int elemr; workspaceptr = workspace; for (elemr = 0; elemr < DCTSIZE; elemr++) { elemptr = sample_data[elemr] + start_col; #if DCTSIZE == 8 /* unroll the inner loop */ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; #else { register int elemc; for (elemc = DCTSIZE; elemc > 0; elemc--) { *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; } } #endif } } jpeg_fdct_llm(workspace); { register MULTIPLIER temp; register MULTIPLIER qval; register int i; register JCOEFPTR output_ptr = coef_blocks[bi]; for (i = 0; i < DCTSIZE2; i++) { qval = qtbl->divisors[i]; temp = (MULTIPLIER) workspace[ZAG[i]]; /* Divide the coefficient value by qval, ensuring proper rounding. * Since C does not specify the direction of rounding for negative * quotients, we have to force the dividend positive for portability. * * In most files, at least half of the output values will be zero * (at default quantization settings, more like three-quarters...) * so we should ensure that this case is fast. On many machines, * a comparison is enough cheaper than a divide to make a special test * a win. Since both inputs will be nonnegative, we need only test * for a < b to discover whether a/b is 0. * If your machine's division is fast enough, define FAST_DIVIDE. */ #ifdef FAST_DIVIDE #define DIVIDE_BY(a,b) a /= b #else #define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0 #endif if (temp < 0) { temp = -temp; temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); temp = -temp; } else { temp += qval>>1; /* for rounding */ DIVIDE_BY(temp, qval); } output_ptr[i] = (JCOEF) temp; } } } } /* * Initialize FDCT manager. */ GLOBAL void jinit_forward_dct (j_compress_ptr cinfo) { my_fdct_ptr fdct; fdct = (my_fdct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_fdct_controller)); cinfo->fdct = (struct jpeg_forward_dct *) fdct; fdct->pub.start_pass = start_pass; fdct->pub.forward_DCT = forward_DCT; } \ No newline at end of file diff --git a/Independent JPEG Group/jchuff.c b/Independent JPEG Group/jchuff.c new file mode 100644 index 0000000..1179476 --- /dev/null +++ b/Independent JPEG Group/jchuff.c @@ -0,0 +1 @@ +/* * jchuff.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy encoding routines. * * Much of the complexity here has to do with supporting output suspension. * If the data destination module demands suspension, we want to be able to * back up to the start of the current MCU. To do this, we copy state * variables into local working storage, and update them back to the * permanent JPEG objects only upon successful completion of an MCU. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Expanded entropy encoder object for Huffman encoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { INT32 put_buffer; /* current bit-accumulation buffer */ int put_bits; /* # of bits now in it */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; typedef struct { struct jpeg_entropy_encoder pub; /* public fields */ savable_state saved; /* Bit buffer & DC state at start of MCU */ /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ int next_restart_num; /* next restart number to write (0-7) */ #ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */ long * dc_count_ptrs[NUM_HUFF_TBLS]; long * ac_count_ptrs[NUM_HUFF_TBLS]; #endif } huff_entropy_encoder; typedef huff_entropy_encoder * huff_entropy_ptr; /* Working state while writing an MCU. * This struct contains all the fields that are needed by subroutines. */ typedef struct { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ savable_state cur; /* Current bit buffer & DC state */ j_compress_ptr cinfo; /* dump_buffer needs access to this */ } working_state; /* Forward declarations */ METHODDEF boolean encode_mcu_huff JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF void finish_pass_huff JPP((j_compress_ptr cinfo)); #ifdef ENTROPY_OPT_SUPPORTED METHODDEF boolean encode_mcu_gather JPP((j_compress_ptr cinfo, JBLOCKROW *MCU_data)); METHODDEF void finish_pass_gather JPP((j_compress_ptr cinfo)); #endif LOCAL void fix_huff_tbl JPP((JCHUFF_TBL * htbl)); /* * Initialize for a Huffman-compressed scan. * If gather_statistics is TRUE, we do not output anything during the scan, * just count the Huffman symbols used and generate Huffman code tables. */ METHODDEF void start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, dctbl, actbl; jpeg_component_info * compptr; if (gather_statistics) { #ifdef ENTROPY_OPT_SUPPORTED entropy->pub.encode_mcu = encode_mcu_gather; entropy->pub.finish_pass = finish_pass_gather; #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { entropy->pub.encode_mcu = encode_mcu_huff; entropy->pub.finish_pass = finish_pass_huff; } for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; dctbl = compptr->dc_tbl_no; actbl = compptr->ac_tbl_no; /* Make sure requested tables are present */ /* (In gather mode, tables need not be allocated yet) */ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || (cinfo->dc_huff_tbl_ptrs[dctbl] == NULL && !gather_statistics)) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); if (actbl < 0 || actbl >= NUM_HUFF_TBLS || (cinfo->ac_huff_tbl_ptrs[actbl] == NULL && !gather_statistics)) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); if (gather_statistics) { #ifdef ENTROPY_OPT_SUPPORTED /* Allocate and zero the statistics tables */ /* Note that gen_huff_coding expects 257 entries in each table! */ if (entropy->dc_count_ptrs[dctbl] == NULL) entropy->dc_count_ptrs[dctbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 257 * SIZEOF(long)); MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); if (entropy->ac_count_ptrs[actbl] == NULL) entropy->ac_count_ptrs[actbl] = (long *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 257 * SIZEOF(long)); MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); #endif } else { /* Compute derived values for Huffman tables */ /* We may do this more than once for a table, but it's not expensive */ fix_huff_tbl((JCHUFF_TBL *) cinfo->dc_huff_tbl_ptrs[dctbl]); fix_huff_tbl((JCHUFF_TBL *) cinfo->ac_huff_tbl_ptrs[actbl]); } /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* Initialize bit buffer to empty */ entropy->saved.put_buffer = 0; entropy->saved.put_bits = 0; /* Initialize restart stuff */ entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num = 0; } LOCAL void fix_huff_tbl (JCHUFF_TBL * htbl) /* Compute the derived values for a Huffman table */ { int p, i, l, lastp, si; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Figure C.1: make table of Huffman code length for each symbol */ /* Note that this is in code-length order. */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= (int) htbl->pub.bits[l]; i++) huffsize[p++] = (char) l; } huffsize[p] = 0; lastp = p; /* Figure C.2: generate the codes themselves */ /* Note that this is in code-length order. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } /* Figure C.3: generate encoding tables */ /* These are code and size indexed by symbol value */ /* Set any codeless symbols to have code length 0; * this allows emit_bits to detect any attempt to emit such symbols. */ MEMZERO(htbl->ehufsi, SIZEOF(htbl->ehufsi)); for (p = 0; p < lastp; p++) { htbl->ehufco[htbl->pub.huffval[p]] = huffcode[p]; htbl->ehufsi[htbl->pub.huffval[p]] = huffsize[p]; } } /* Outputting bytes to the file */ /* Emit a byte, taking 'action' if must suspend. */ #define emit_byte(state,val,action) \ { *(state)->next_output_byte++ = (JOCTET) (val); \ if (--(state)->free_in_buffer == 0) \ if (! dump_buffer(state)) \ { action; } } LOCAL boolean dump_buffer (working_state * state) /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ { struct jpeg_destination_mgr * dest = state->cinfo->dest; if (! (*dest->empty_output_buffer) (state->cinfo)) return FALSE; /* After a successful buffer dump, must reset buffer pointers */ state->next_output_byte = dest->next_output_byte; state->free_in_buffer = dest->free_in_buffer; return TRUE; } /* Outputting bits to the file */ /* Only the right 24 bits of put_buffer are used; the valid bits are * left-justified in this part. At most 16 bits can be passed to emit_bits * in one call, and we never retain more than 7 bits in put_buffer * between calls, so 24 bits are sufficient. */ INLINE LOCAL boolean emit_bits (working_state * state, unsigned int code, int size) /* Emit some bits; return TRUE if successful, FALSE if must suspend */ { /* This routine is heavily used, so it's worth coding tightly. */ register INT32 put_buffer = (INT32) code; register int put_bits = state->cur.put_bits; /* if size is 0, caller used an invalid Huffman table entry */ if (size == 0) ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); put_buffer &= (((INT32) 1)<cur.put_buffer; /* and merge with old buffer contents */ while (put_bits >= 8) { int c = (int) ((put_buffer >> 16) & 0xFF); emit_byte(state, c, return FALSE); if (c == 0xFF) { /* need to stuff a zero byte? */ emit_byte(state, 0, return FALSE); } put_buffer <<= 8; put_bits -= 8; } state->cur.put_buffer = put_buffer; /* update state variables */ state->cur.put_bits = put_bits; return TRUE; } LOCAL boolean flush_bits (working_state * state) { if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ return FALSE; state->cur.put_buffer = 0; /* and reset bit-buffer to empty */ state->cur.put_bits = 0; return TRUE; } /* Encode a single block's worth of coefficients */ LOCAL boolean encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, JCHUFF_TBL *dctbl, JCHUFF_TBL *actbl) { register int temp, temp2; register int nbits; register int k, r, i; /* Encode the DC coefficient difference per section F.1.2.1 */ temp = temp2 = block[0] - last_dc_val; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* For a negative input, want temp2 = bitwise complement of abs(input) */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { nbits++; temp >>= 1; } /* Emit the Huffman-coded symbol for the number of bits */ if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (nbits) /* emit_bits rejects calls with size 0 */ if (! emit_bits(state, (unsigned int) temp2, nbits)) return FALSE; /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { if ((temp = block[k]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) return FALSE; r -= 16; } temp2 = temp; if (temp < 0) { temp = -temp; /* temp is abs value of input */ /* This code assumes we are on a two's complement machine */ temp2--; } /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) nbits++; /* Emit Huffman symbol for run length / number of bits */ i = (r << 4) + nbits; if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) return FALSE; /* Emit that number of bits of the value, if positive, */ /* or the complement of its magnitude, if negative. */ if (! emit_bits(state, (unsigned int) temp2, nbits)) return FALSE; r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) return FALSE; return TRUE; } /* * Emit a restart marker & resynchronize predictions. */ LOCAL boolean emit_restart (working_state * state, int restart_num) { int ci; if (! flush_bits(state)) return FALSE; emit_byte(state, 0xFF, return FALSE); emit_byte(state, JPEG_RST0 + restart_num, return FALSE); /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) state->cur.last_dc_val[ci] = 0; /* The restart counter is not updated until we successfully write the MCU. */ return TRUE; } /* * Encode and output one MCU's worth of Huffman-compressed coefficients. */ METHODDEF boolean encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; int blkn, ci; jpeg_component_info * compptr; /* Load up working state */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; state.cur = entropy->saved; state.cinfo = cinfo; /* Emit restart marker if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! emit_restart(&state, entropy->next_restart_num)) return FALSE; } /* Encode the MCU data blocks */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; if (! encode_one_block(&state, MCU_data[blkn][0], state.cur.last_dc_val[ci], (JCHUFF_TBL *) cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no], (JCHUFF_TBL *) cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no])) return FALSE; /* Update last_dc_val */ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; } /* Completed MCU, so update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; entropy->saved = state.cur; /* Update restart-interval state too */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { entropy->restarts_to_go = cinfo->restart_interval; entropy->next_restart_num++; entropy->next_restart_num &= 7; } entropy->restarts_to_go--; } return TRUE; } /* * Finish up at the end of a Huffman-compressed scan. */ METHODDEF void finish_pass_huff (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; working_state state; /* Load up working state ... flush_bits needs it */ state.next_output_byte = cinfo->dest->next_output_byte; state.free_in_buffer = cinfo->dest->free_in_buffer; state.cur = entropy->saved; state.cinfo = cinfo; /* Flush out the last data */ if (! flush_bits(&state)) ERREXIT(cinfo, JERR_CANT_SUSPEND); /* Update state */ cinfo->dest->next_output_byte = state.next_output_byte; cinfo->dest->free_in_buffer = state.free_in_buffer; entropy->saved = state.cur; } /* * Huffman coding optimization. * * This actually is optimization, in the sense that we find the best possible * Huffman table(s) for the given data. We first scan the supplied data and * count the number of uses of each symbol that is to be Huffman-coded. * (This process must agree with the code above.) Then we build an * optimal Huffman coding tree for the observed counts. * * The JPEG standard requires Huffman codes to be no more than 16 bits long. * If some symbols have a very small but nonzero probability, the Huffman tree * must be adjusted to meet the code length restriction. We currently use * the adjustment method suggested in the JPEG spec. This method is *not* * optimal; it may not choose the best possible limited-length code. But * since the symbols involved are infrequently used, it's not clear that * going to extra trouble is worthwhile. */ #ifdef ENTROPY_OPT_SUPPORTED /* Process a single block's worth of coefficients */ LOCAL void htest_one_block (JCOEFPTR block, int last_dc_val, long dc_counts[], long ac_counts[]) { register int temp; register int nbits; register int k, r; /* Encode the DC coefficient difference per section F.1.2.1 */ temp = block[0] - last_dc_val; if (temp < 0) temp = -temp; /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 0; while (temp) { nbits++; temp >>= 1; } /* Count the Huffman symbol for the number of bits */ dc_counts[nbits]++; /* Encode the AC coefficients per section F.1.2.2 */ r = 0; /* r = run length of zeros */ for (k = 1; k < DCTSIZE2; k++) { if ((temp = block[k]) == 0) { r++; } else { /* if run length > 15, must emit special run-length-16 codes (0xF0) */ while (r > 15) { ac_counts[0xF0]++; r -= 16; } /* Find the number of bits needed for the magnitude of the coefficient */ if (temp < 0) temp = -temp; /* Find the number of bits needed for the magnitude of the coefficient */ nbits = 1; /* there must be at least one 1 bit */ while ((temp >>= 1)) nbits++; /* Count Huffman symbol for run length / number of bits */ ac_counts[(r << 4) + nbits]++; r = 0; } } /* If the last coef(s) were zero, emit an end-of-block code */ if (r > 0) ac_counts[0]++; } /* * Trial-encode one MCU's worth of Huffman-compressed coefficients. * No data is actually output, so no suspension return is possible. */ METHODDEF boolean encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int blkn, ci; jpeg_component_info * compptr; /* Take care of restart intervals if needed */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) { /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; /* Update restart state */ entropy->restarts_to_go = cinfo->restart_interval; } entropy->restarts_to_go--; } for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; htest_one_block(MCU_data[blkn][0], entropy->saved.last_dc_val[ci], entropy->dc_count_ptrs[compptr->dc_tbl_no], entropy->ac_count_ptrs[compptr->ac_tbl_no]); entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; } return TRUE; } /* Generate the optimal coding for the given counts, initialize htbl */ LOCAL void gen_huff_coding (j_compress_ptr cinfo, JHUFF_TBL *htbl, long freq[]) { #define MAX_CLEN 32 /* assumed maximum initial code length */ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */ int codesize[257]; /* codesize[k] = code length of symbol k */ int others[257]; /* next symbol in current branch of tree */ int c1, c2; int p, i, j; long v; /* This algorithm is explained in section K.2 of the JPEG standard */ MEMZERO(bits, SIZEOF(bits)); MEMZERO(codesize, SIZEOF(codesize)); for (i = 0; i < 257; i++) others[i] = -1; /* init links to empty */ freq[256] = 1; /* make sure there is a nonzero count */ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees * that no real symbol is given code-value of all ones, because 256 * will be placed in the largest codeword category. */ /* Huffman's basic algorithm to assign optimal code lengths to symbols */ for (;;) { /* Find the smallest nonzero frequency, set c1 = its symbol */ /* In case of ties, take the larger symbol number */ c1 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v) { v = freq[i]; c1 = i; } } /* Find the next smallest nonzero frequency, set c2 = its symbol */ /* In case of ties, take the larger symbol number */ c2 = -1; v = 1000000000L; for (i = 0; i <= 256; i++) { if (freq[i] && freq[i] <= v && i != c1) { v = freq[i]; c2 = i; } } /* Done if we've merged everything into one frequency */ if (c2 < 0) break; /* Else merge the two counts/trees */ freq[c1] += freq[c2]; freq[c2] = 0; /* Increment the codesize of everything in c1's tree branch */ codesize[c1]++; while (others[c1] >= 0) { c1 = others[c1]; codesize[c1]++; } others[c1] = c2; /* chain c2 onto c1's tree branch */ /* Increment the codesize of everything in c2's tree branch */ codesize[c2]++; while (others[c2] >= 0) { c2 = others[c2]; codesize[c2]++; } } /* Now count the number of symbols of each code length */ for (i = 0; i <= 256; i++) { if (codesize[i]) { /* The JPEG standard seems to think that this can't happen, */ /* but I'm paranoid... */ if (codesize[i] > MAX_CLEN) ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); bits[codesize[i]]++; } } /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure * Huffman procedure assigned any such lengths, we must adjust the coding. * Here is what the JPEG spec says about how this next bit works: * Since symbols are paired for the longest Huffman code, the symbols are * removed from this length category two at a time. The prefix for the pair * (which is one bit shorter) is allocated to one of the pair; then, * skipping the BITS entry for that prefix length, a code word from the next * shortest nonzero BITS entry is converted into a prefix for two code words * one bit longer. */ for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { j = i - 2; /* find length of new prefix to be used */ while (bits[j] == 0) j--; bits[i] -= 2; /* remove two symbols */ bits[i-1]++; /* one goes in this length */ bits[j+1] += 2; /* two new symbols in this length */ bits[j]--; /* symbol of this length is now a prefix */ } } /* Remove the count for the pseudo-symbol 256 from the largest codelength */ while (bits[i] == 0) /* find largest codelength still in use */ i--; bits[i]--; /* Return final symbol counts (only for lengths 0..16) */ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); /* Return a list of the symbols sorted by code length */ /* It's not real clear to me why we don't need to consider the codelength * changes made above, but the JPEG spec seems to think this works. */ p = 0; for (i = 1; i <= MAX_CLEN; i++) { for (j = 0; j <= 255; j++) { if (codesize[j] == i) { htbl->huffval[p] = (UINT8) j; p++; } } } /* Set sent_table FALSE so updated table will be written to JPEG file. */ htbl->sent_table = FALSE; } /* * Finish up a statistics-gathering pass and create the new Huffman tables. */ METHODDEF void finish_pass_gather (j_compress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, dctbl, actbl; jpeg_component_info * compptr; JHUFF_TBL **htblptr; boolean did_dc[NUM_HUFF_TBLS]; boolean did_ac[NUM_HUFF_TBLS]; /* It's important not to apply gen_huff_coding more than once per table, * because it clobbers the input frequency counts! */ MEMZERO(did_dc, SIZEOF(did_dc)); MEMZERO(did_ac, SIZEOF(did_ac)); for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; dctbl = compptr->dc_tbl_no; actbl = compptr->ac_tbl_no; if (! did_dc[dctbl]) { htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); gen_huff_coding(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); did_dc[dctbl] = TRUE; } if (! did_ac[actbl]) { htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); gen_huff_coding(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); did_ac[actbl] = TRUE; } } } #endif /* ENTROPY_OPT_SUPPORTED */ /* * Module initialization routine for Huffman entropy encoding. */ GLOBAL void jinit_huff_encoder (j_compress_ptr cinfo) { huff_entropy_ptr entropy; entropy = (huff_entropy_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_encoder)); cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; entropy->pub.start_pass = start_pass_huff; #ifdef ENTROPY_OPT_SUPPORTED /* Mark count tables unallocated */ { int i; for (i = 0; i < NUM_HUFF_TBLS; i++) entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; } #endif } \ No newline at end of file diff --git a/Independent JPEG Group/jcmainct.c b/Independent JPEG Group/jcmainct.c new file mode 100644 index 0000000..e507b0f --- /dev/null +++ b/Independent JPEG Group/jcmainct.c @@ -0,0 +1 @@ +/* * jcmainct.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main buffer controller for compression. * The main buffer lies between the pre-processor and the JPEG * compressor proper; it holds downsampled data in the JPEG colorspace. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private buffer controller object */ typedef struct { struct jpeg_c_main_controller pub; /* public fields */ JDIMENSION cur_mcu_row; /* number of current MCU row */ JDIMENSION rowgroup_ctr; /* counts row groups received in MCU row */ JDIMENSION mcu_ctr; /* counts MCUs output from current row */ boolean suspended; /* remember if we suspended output */ J_BUF_MODE pass_mode; /* current operating mode */ /* If using full-image storage, this array holds pointers to virtual-array * control blocks for each component. Unused if not full-image storage. */ jvirt_sarray_ptr virtual[MAX_COMPONENTS]; /* If using just a strip buffer, this points to the entire set of buffers * (we allocate one for each component). In the virtual-array case, this * points to the currently accessible strips of the virtual arrays. */ JSAMPARRAY buffer[MAX_COMPONENTS]; /* This vector points to the current strips of the components being written * during the current scan. */ JSAMPARRAY cur_buffer[MAX_COMPS_IN_SCAN]; } my_main_controller; typedef my_main_controller * my_main_ptr; /* Forward declarations */ METHODDEF void process_data_simple_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); METHODDEF void process_data_buffer_main JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); /* * Initialize for a processing pass. */ METHODDEF void start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, cindex; main->cur_mcu_row = 0; /* initialize counters */ main->rowgroup_ctr = 0; main->mcu_ctr = 0; main->suspended = FALSE; main->pass_mode = pass_mode; /* save mode for use by process_data */ switch (pass_mode) { case JBUF_PASS_THRU: if (main->virtual[0] != NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); main->pub.process_data = process_data_simple_main; /* The output-strip pointers can be set up once for the whole pass. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { cindex = cinfo->cur_comp_info[ci]->component_index; main->cur_buffer[ci] = main->buffer[cindex]; } break; case JBUF_SAVE_SOURCE: case JBUF_CRANK_DEST: case JBUF_SAVE_AND_PASS: if (main->virtual[0] == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); main->pub.process_data = process_data_buffer_main; break; default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } } /* * Process some data. * This routine handles the simple pass-through mode, * where we have only a strip buffer. */ METHODDEF void process_data_simple_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; while (*in_row_ctr < in_rows_avail) { /* Read input data if we haven't filled the main buffer yet */ if (main->rowgroup_ctr < DCTSIZE) (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, main->buffer, &main->rowgroup_ctr, (JDIMENSION) DCTSIZE); /* If we have a full MCU row buffered, emit data. */ /* Note that preprocessor ensures this will be true at bottom of image. */ if (main->rowgroup_ctr == DCTSIZE) { (*cinfo->coef->compress_data) (cinfo, main->cur_buffer, &main->mcu_ctr); /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ if (main->mcu_ctr < cinfo->MCUs_per_row) { if (! main->suspended) { (*in_row_ctr)--; main->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ if (main->suspended) { (*in_row_ctr)++; main->suspended = FALSE; } main->mcu_ctr = 0; main->rowgroup_ctr = 0; } } } /* * Process some data. * This routine handles all of the modes that use a full-size buffer. */ METHODDEF void process_data_buffer_main (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, cindex; jpeg_component_info *compptr; boolean writing = (main->pass_mode != JBUF_CRANK_DEST); /* Realign the virtual buffers if at the start of an MCU row. */ if (main->rowgroup_ctr == 0) { /* Note: during a read pass it is not necessary to reposition the * buffers of components not being output. This could save some I/O, * but is not currently implemented. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { main->buffer[ci] = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, main->virtual[ci], main->cur_mcu_row * (compptr->v_samp_factor * DCTSIZE), writing); } /* Set the output-strip pointers too. */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { cindex = cinfo->cur_comp_info[ci]->component_index; main->cur_buffer[ci] = main->buffer[cindex]; } /* In a read pass, pretend we just read some source data. */ if (! writing) { *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; main->rowgroup_ctr = DCTSIZE; } } /* If a write pass, read input data until the current MCU strip is full. */ /* Note: preprocessor will pad if necessary to fill the last MCU strip. */ if (writing) { (*cinfo->prep->pre_process_data) (cinfo, input_buf, in_row_ctr, in_rows_avail, main->buffer, &main->rowgroup_ctr, (JDIMENSION) DCTSIZE); /* Quit if we didn't yet fill the MCU strip. */ if (main->rowgroup_ctr < DCTSIZE) return; } /* Emit data, unless this is a sink-only pass. */ if (main->pass_mode != JBUF_SAVE_SOURCE) { (*cinfo->coef->compress_data) (cinfo, main->cur_buffer, &main->mcu_ctr); /* If compressor did not consume the whole row, then we must need to * suspend processing and return to the application. In this situation * we pretend we didn't yet consume the last input row; otherwise, if * it happened to be the last row of the image, the application would * think we were done. */ if (main->mcu_ctr < cinfo->MCUs_per_row) { if (! main->suspended) { (*in_row_ctr)--; main->suspended = TRUE; } return; } /* We did finish the row. Undo our little suspension hack if a previous * call suspended; then mark the main buffer empty. */ if (main->suspended) { (*in_row_ctr)++; main->suspended = FALSE; } } /* If get here, we are done with this MCU strip. Mark buffer empty. */ main->mcu_ctr = 0; main->rowgroup_ctr = 0; main->cur_mcu_row++; } /* * Initialize main buffer controller. */ GLOBAL void jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main; int ci; jpeg_component_info *compptr; main = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = (struct jpeg_c_main_controller *) main; main->pub.start_pass = start_pass_main; /* Create the buffer. It holds downsampled data, so each component * may be of a different size. */ if (need_full_buffer) { /* Allocate a full-image virtual array for each component */ /* Note we implicitly pad the bottom to a multiple of the MCU height */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { main->virtual[ci] = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, compptr->height_in_blocks * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); } } else { main->virtual[0] = NULL; /* flag for no virtual arrays */ /* Allocate a strip buffer for each component */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { main->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * DCTSIZE, (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); } } } \ No newline at end of file diff --git a/Independent JPEG Group/jcmarker.c b/Independent JPEG Group/jcmarker.c new file mode 100644 index 0000000..39715fe --- /dev/null +++ b/Independent JPEG Group/jcmarker.c @@ -0,0 +1 @@ +/* * jcmarker.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write JPEG datastream markers. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP1 = 0xe1, M_APP2 = 0xe2, M_APP3 = 0xe3, M_APP4 = 0xe4, M_APP5 = 0xe5, M_APP6 = 0xe6, M_APP7 = 0xe7, M_APP8 = 0xe8, M_APP9 = 0xe9, M_APP10 = 0xea, M_APP11 = 0xeb, M_APP12 = 0xec, M_APP13 = 0xed, M_APP14 = 0xee, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; /* * Basic output routines. * * Note that we do not support suspension while writing a marker. * Therefore, an application using suspension must ensure that there is * enough buffer space for the initial markers (typ. 600-700 bytes) before * calling jpeg_start_compress, and enough space to write the trailing EOI * (a few bytes) before calling jpeg_finish_compress. Multipass compression * modes are not supported at all with suspension, so those two are the only * points where markers will be written. */ LOCAL void emit_byte (j_compress_ptr cinfo, int val) /* Emit a byte */ { struct jpeg_destination_mgr * dest = cinfo->dest; *(dest->next_output_byte)++ = (JOCTET) val; if (--dest->free_in_buffer == 0) { if (! (*dest->empty_output_buffer) (cinfo)) ERREXIT(cinfo, JERR_CANT_SUSPEND); } } LOCAL void emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) /* Emit a marker code */ { emit_byte(cinfo, 0xFF); emit_byte(cinfo, (int) mark); } LOCAL void emit_2bytes (j_compress_ptr cinfo, int value) /* Emit a 2-byte integer; these are always MSB first in JPEG files */ { emit_byte(cinfo, (value >> 8) & 0xFF); emit_byte(cinfo, value & 0xFF); } /* * Routines to write specific marker types. */ LOCAL int emit_dqt (j_compress_ptr cinfo, int index) /* Emit a DQT marker */ /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ { JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; int prec; int i; if (qtbl == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); prec = 0; for (i = 0; i < DCTSIZE2; i++) { if (qtbl->quantval[i] > 255) prec = 1; } if (! qtbl->sent_table) { emit_marker(cinfo, M_DQT); emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); emit_byte(cinfo, index + (prec<<4)); for (i = 0; i < DCTSIZE2; i++) { if (prec) emit_byte(cinfo, qtbl->quantval[i] >> 8); emit_byte(cinfo, qtbl->quantval[i] & 0xFF); } qtbl->sent_table = TRUE; } return prec; } LOCAL void emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) /* Emit a DHT marker */ { JHUFF_TBL * htbl; int length, i; if (is_ac) { htbl = cinfo->ac_huff_tbl_ptrs[index]; index += 0x10; /* output index has AC bit set */ } else { htbl = cinfo->dc_huff_tbl_ptrs[index]; } if (htbl == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); if (! htbl->sent_table) { emit_marker(cinfo, M_DHT); length = 0; for (i = 1; i <= 16; i++) length += htbl->bits[i]; emit_2bytes(cinfo, length + 2 + 1 + 16); emit_byte(cinfo, index); for (i = 1; i <= 16; i++) emit_byte(cinfo, htbl->bits[i]); for (i = 0; i < length; i++) emit_byte(cinfo, htbl->huffval[i]); htbl->sent_table = TRUE; } } LOCAL void emit_dac (j_compress_ptr cinfo) /* Emit a DAC marker */ /* Since the useful info is so small, we want to emit all the tables in */ /* one DAC marker. Therefore this routine does its own scan of the table. */ { #ifdef C_ARITH_CODING_SUPPORTED char dc_in_use[NUM_ARITH_TBLS]; char ac_in_use[NUM_ARITH_TBLS]; int length, i; for (i = 0; i < NUM_ARITH_TBLS; i++) dc_in_use[i] = ac_in_use[i] = 0; for (i = 0; i < cinfo->num_components; i++) { dc_in_use[cinfo->comp_info[i].dc_tbl_no] = 1; ac_in_use[cinfo->comp_info[i].ac_tbl_no] = 1; } length = 0; for (i = 0; i < NUM_ARITH_TBLS; i++) length += dc_in_use[i] + ac_in_use[i]; emit_marker(cinfo, M_DAC); emit_2bytes(cinfo, length*2 + 2); for (i = 0; i < NUM_ARITH_TBLS; i++) { if (dc_in_use[i]) { emit_byte(cinfo, i); emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); } if (ac_in_use[i]) { emit_byte(cinfo, i + 0x10); emit_byte(cinfo, cinfo->arith_ac_K[i]); } } #endif /* C_ARITH_CODING_SUPPORTED */ } LOCAL void emit_dri (j_compress_ptr cinfo) /* Emit a DRI marker */ { emit_marker(cinfo, M_DRI); emit_2bytes(cinfo, 4); /* fixed length */ emit_2bytes(cinfo, (int) cinfo->restart_interval); } LOCAL void emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) /* Emit a SOF marker */ { int ci; jpeg_component_info *compptr; emit_marker(cinfo, code); emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ /* Make sure image isn't bigger than SOF field can handle */ if ((long) cinfo->image_height > 65535L || (long) cinfo->image_width > 65535L) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); emit_byte(cinfo, cinfo->data_precision); emit_2bytes(cinfo, (int) cinfo->image_height); emit_2bytes(cinfo, (int) cinfo->image_width); emit_byte(cinfo, cinfo->num_components); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { emit_byte(cinfo, compptr->component_id); emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); emit_byte(cinfo, compptr->quant_tbl_no); } } LOCAL void emit_sos (j_compress_ptr cinfo) /* Emit a SOS marker */ { int i; emit_marker(cinfo, M_SOS); emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ emit_byte(cinfo, cinfo->comps_in_scan); for (i = 0; i < cinfo->comps_in_scan; i++) { emit_byte(cinfo, cinfo->cur_comp_info[i]->component_id); emit_byte(cinfo, (cinfo->cur_comp_info[i]->dc_tbl_no << 4) + cinfo->cur_comp_info[i]->ac_tbl_no); } emit_byte(cinfo, 0); /* Spectral selection start */ emit_byte(cinfo, DCTSIZE2-1); /* Spectral selection end */ emit_byte(cinfo, 0); /* Successive approximation */ } LOCAL void emit_jfif_app0 (j_compress_ptr cinfo) /* Emit a JFIF-compliant APP0 marker */ { /* * Length of APP0 block (2 bytes) * Block ID (4 bytes - ASCII "JFIF") * Zero byte (1 byte to terminate the ID string) * Version Major, Minor (2 bytes - 0x01, 0x01) * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) * Xdpu (2 bytes - dots per unit horizontal) * Ydpu (2 bytes - dots per unit vertical) * Thumbnail X size (1 byte) * Thumbnail Y size (1 byte) */ emit_marker(cinfo, M_APP0); emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */ emit_byte(cinfo, 0x46); emit_byte(cinfo, 0x49); emit_byte(cinfo, 0x46); emit_byte(cinfo, 0); /* We currently emit version code 1.01 since we use no 1.02 features. * This may avoid complaints from some older decoders. */ emit_byte(cinfo, 1); /* Major version */ emit_byte(cinfo, 1); /* Minor version */ emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ emit_2bytes(cinfo, (int) cinfo->X_density); emit_2bytes(cinfo, (int) cinfo->Y_density); emit_byte(cinfo, 0); /* No thumbnail image */ emit_byte(cinfo, 0); } LOCAL void emit_adobe_app14 (j_compress_ptr cinfo) /* Emit an Adobe APP14 marker */ { /* * Length of APP14 block (2 bytes) * Block ID (5 bytes - ASCII "Adobe") * Version Number (2 bytes - currently 100) * Flags0 (2 bytes - currently 0) * Flags1 (2 bytes - currently 0) * Color transform (1 byte) * * Although Adobe TN 5116 mentions Version = 101, all the Adobe files * now in circulation seem to use Version = 100, so that's what we write. * * We write the color transform byte as 1 if the JPEG color space is * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with * whether the encoder performed a transformation, which is pretty useless. */ emit_marker(cinfo, M_APP14); emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */ emit_byte(cinfo, 0x64); emit_byte(cinfo, 0x6F); emit_byte(cinfo, 0x62); emit_byte(cinfo, 0x65); emit_2bytes(cinfo, 100); /* Version */ emit_2bytes(cinfo, 0); /* Flags0 */ emit_2bytes(cinfo, 0); /* Flags1 */ switch (cinfo->jpeg_color_space) { case JCS_YCbCr: emit_byte(cinfo, 1); /* Color transform = 1 */ break; case JCS_YCCK: emit_byte(cinfo, 2); /* Color transform = 2 */ break; default: emit_byte(cinfo, 0); /* Color transform = 0 */ break; } } /* * This routine is exported for possible use by applications. * The intended use is to emit COM or APPn markers after calling * jpeg_start_compress() and before the first jpeg_write_scanlines() call * (hence, after write_file_header but before write_frame_header). * Other uses are not guaranteed to produce desirable results. */ METHODDEF void write_any_marker (j_compress_ptr cinfo, int marker, JOCTET *dataptr, unsigned int datalen) /* Emit an arbitrary marker with parameters */ { if (datalen <= (unsigned int) 65533) { /* safety check */ emit_marker(cinfo, (JPEG_MARKER) marker); emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */ while (datalen--) { emit_byte(cinfo, *dataptr); dataptr++; } } } /* * Write datastream header. * This consists of an SOI and optional APPn markers. * We recommend use of the JFIF marker, but not the Adobe marker, * when using YCbCr or grayscale data. The JFIF marker should NOT * be used for any other JPEG colorspace. The Adobe marker is helpful * to distinguish RGB, CMYK, and YCCK colorspaces. * Note that an application can write additional header markers after * jpeg_start_decompress returns. */ METHODDEF void write_file_header (j_compress_ptr cinfo) { emit_marker(cinfo, M_SOI); /* first the SOI */ if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */ emit_jfif_app0(cinfo); if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ emit_adobe_app14(cinfo); } /* * Write frame header. * This consists of DQT and SOFn markers. * Note that we do not emit the SOF until we have emitted the DQT(s). * This avoids compatibility problems with incorrect implementations that * try to error-check the quant table numbers as soon as they see the SOF. */ METHODDEF void write_frame_header (j_compress_ptr cinfo) { int i, prec; boolean is_baseline; /* Emit DQT for each quantization table. * Note that emit_dqt() suppresses any duplicate tables. */ prec = 0; for (i = 0; i < cinfo->num_components; i++) prec += emit_dqt(cinfo, cinfo->comp_info[i].quant_tbl_no); /* now prec is nonzero iff there are any 16-bit quant tables. */ /* Check for a non-baseline specification. * Note we assume that Huffman table numbers won't be changed later. */ is_baseline = TRUE; if (cinfo->arith_code || (cinfo->data_precision != 8)) is_baseline = FALSE; for (i = 0; i < cinfo->num_components; i++) { if (cinfo->comp_info[i].dc_tbl_no > 1 || cinfo->comp_info[i].ac_tbl_no > 1) is_baseline = FALSE; } if (prec && is_baseline) { is_baseline = FALSE; /* If it's baseline except for quantizer size, warn the user */ TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); } /* Emit the proper SOF marker */ if (cinfo->arith_code) emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */ else if (is_baseline) emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */ else emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */ } /* * Write scan header. * This consists of DHT or DAC markers, optional DRI, and SOS. * Compressed data will be written following the SOS. */ METHODDEF void write_scan_header (j_compress_ptr cinfo) { int i; if (cinfo->arith_code) { /* Emit arith conditioning info. We will have some duplication * if the file has multiple scans, but it's so small it's hardly * worth worrying about. */ emit_dac(cinfo); } else { /* Emit Huffman tables. * Note that emit_dht() suppresses any duplicate tables. */ for (i = 0; i < cinfo->comps_in_scan; i++) { emit_dht(cinfo, cinfo->cur_comp_info[i]->dc_tbl_no, FALSE); emit_dht(cinfo, cinfo->cur_comp_info[i]->ac_tbl_no, TRUE); } } /* Emit DRI if required --- note that DRI value could change for each scan. * If it doesn't, a tiny amount of space is wasted in multiple-scan files. * We assume DRI will never be nonzero for one scan and zero for a later one. */ if (cinfo->restart_interval) emit_dri(cinfo); emit_sos(cinfo); } /* * Write datastream trailer. */ METHODDEF void write_file_trailer (j_compress_ptr cinfo) { emit_marker(cinfo, M_EOI); } /* * Write an abbreviated table-specification datastream. * This consists of SOI, DQT and DHT tables, and EOI. * Any table that is defined and not marked sent_table = TRUE will be * emitted. Note that all tables will be marked sent_table = TRUE at exit. */ METHODDEF void write_tables_only (j_compress_ptr cinfo) { int i; emit_marker(cinfo, M_SOI); for (i = 0; i < NUM_QUANT_TBLS; i++) { if (cinfo->quant_tbl_ptrs[i] != NULL) (void) emit_dqt(cinfo, i); } if (! cinfo->arith_code) { for (i = 0; i < NUM_HUFF_TBLS; i++) { if (cinfo->dc_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, FALSE); if (cinfo->ac_huff_tbl_ptrs[i] != NULL) emit_dht(cinfo, i, TRUE); } } emit_marker(cinfo, M_EOI); } /* * Initialize the marker writer module. */ GLOBAL void jinit_marker_writer (j_compress_ptr cinfo) { /* Create the subobject */ cinfo->marker = (struct jpeg_marker_writer *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(struct jpeg_marker_writer)); /* Initialize method pointers */ cinfo->marker->write_any_marker = write_any_marker; cinfo->marker->write_file_header = write_file_header; cinfo->marker->write_frame_header = write_frame_header; cinfo->marker->write_scan_header = write_scan_header; cinfo->marker->write_file_trailer = write_file_trailer; cinfo->marker->write_tables_only = write_tables_only; } \ No newline at end of file diff --git a/Independent JPEG Group/jcmaster.c b/Independent JPEG Group/jcmaster.c new file mode 100644 index 0000000..b2d11f6 --- /dev/null +++ b/Independent JPEG Group/jcmaster.c @@ -0,0 +1 @@ +/* * jcmaster.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG compressor. * These routines are concerned with selecting the modules to be executed * and with determining the number of passes and the work to be done in each * pass. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef struct { struct jpeg_comp_master pub; /* public fields */ int pass_number; /* probably need more complex state... */ } my_comp_master; typedef my_comp_master * my_master_ptr; /* * Support routines that do various essential calculations. */ LOCAL void initial_setup (j_compress_ptr cinfo) /* Do computations that are needed before master selection phase */ { int ci; jpeg_component_info *compptr; /* Sanity check on image dimensions */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, JPEG_MAX_DIMENSION); /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* For compression, we never do DCT scaling. */ compptr->DCT_scaled_size = DCTSIZE; /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * DCTSIZE)); /* Size in samples */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) cinfo->max_h_samp_factor); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) cinfo->max_v_samp_factor); /* Mark component needed (this flag isn't actually used for compression) */ compptr->component_needed = TRUE; } } LOCAL void per_scan_setup (j_compress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ { int ci, mcublks; JDIMENSION tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = DCTSIZE; compptr->last_col_width = 1; compptr->last_row_height = 1; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) (cinfo->max_h_samp_factor*DCTSIZE)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = compptr->width_in_blocks % compptr->MCU_width; if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = (int) tmp; tmp = compptr->height_in_blocks % compptr->MCU_height; if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = (int) tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } } /* Convert restart specified in rows to actual MCU count. */ /* Note that count must fit in 16 bits, so we provide limiting. */ if (cinfo->restart_in_rows > 0) { long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); } } /* * Master selection of compression modules. * This is done once at the start of processing an image. We determine * which modules will be used and give them appropriate initialization calls. */ LOCAL void master_selection (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; initial_setup(cinfo); master->pass_number = 0; /* There's not a lot of smarts here right now, but it'll get more * complicated when we have multiple implementations available... */ /* Preprocessing */ jinit_color_converter(cinfo); jinit_downsampler(cinfo); jinit_c_prep_controller(cinfo, FALSE /* for now */); /* Forward DCT */ jinit_forward_dct(cinfo); /* Entropy encoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { #ifdef C_ARITH_CODING_SUPPORTED jinit_arith_encoder(cinfo); #else ERREXIT(cinfo, JERR_ARITH_NOTIMPL); #endif } else jinit_huff_encoder(cinfo); /* Huffman optimization is done by buffering at the main controller. * This will not be the final implementation: it is highly inefficient * because the DCT step is done twice. But it is useful for now. */ jinit_c_coef_controller(cinfo, FALSE /* for now */); jinit_c_main_controller(cinfo, cinfo->optimize_coding); jinit_marker_writer(cinfo); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); /* Write the datastream header (SOI) immediately. * Frame and scan headers are postponed till later. */ (*cinfo->marker->write_file_header) (cinfo); } /* * Per-pass setup. * This is called at the beginning of each pass. We determine which modules * will be active during this pass and give them appropriate start_pass calls. * We also set is_last_pass to indicate whether any more passes will be * required. */ METHODDEF void prepare_for_pass (j_compress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; int ci; /* ???? JUST A QUICK CROCK FOR NOW ??? */ /* For now, handle only single interleaved output scan; */ /* we support two passes for Huffman optimization. */ /* Prepare for single scan containing all components */ if (cinfo->num_components > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPS_IN_SCAN); cinfo->comps_in_scan = cinfo->num_components; for (ci = 0; ci < cinfo->num_components; ci++) { cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; } per_scan_setup(cinfo); /* should do this only if an output pass?? */ if (! cinfo->optimize_coding) { /* Standard single-pass case */ master->pub.call_pass_startup = TRUE; master->pub.is_last_pass = TRUE; (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->downsample->start_pass) (cinfo); (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->fdct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo, FALSE); (*cinfo->coef->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); } else { switch (master->pass_number) { case 0: /* Huffman optimization: run all modules, gather statistics */ master->pub.call_pass_startup = FALSE; master->pub.is_last_pass = FALSE; master->pass_number++; (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->downsample->start_pass) (cinfo); (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->fdct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo, TRUE); (*cinfo->coef->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->main->start_pass) (cinfo, JBUF_SAVE_AND_PASS); break; case 1: /* Second pass: reread data from main buffer */ master->pub.is_last_pass = TRUE; (*cinfo->fdct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo, FALSE); (*cinfo->coef->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); /* We emit frame/scan headers now */ (*cinfo->marker->write_frame_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo); break; } } } /* * Special start-of-pass hook. * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. * In single-pass processing, we need this hook because we don't want to * write frame/scan headers during jpeg_start_compress; we want to let the * application write COM markers etc. between jpeg_start_compress and the * jpeg_write_scanlines loop. * In multi-pass processing, this routine is not used. */ METHODDEF void pass_startup (j_compress_ptr cinfo) { cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ (*cinfo->marker->write_frame_header) (cinfo); (*cinfo->marker->write_scan_header) (cinfo); } /* * Finish up at end of pass. */ METHODDEF void finish_pass (j_compress_ptr cinfo) { /* More complex logic later ??? */ /* The entropy coder needs an end-of-pass call, either to analyze * statistics or to flush its output buffer. */ (*cinfo->entropy->finish_pass) (cinfo); } /* * Initialize master compression control. * This creates my own subrecord and also performs the master selection phase, * which causes other modules to create their subrecords. */ GLOBAL void jinit_master_compress (j_compress_ptr cinfo) { my_master_ptr master; master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_comp_master)); cinfo->master = (struct jpeg_comp_master *) master; master->pub.prepare_for_pass = prepare_for_pass; master->pub.pass_startup = pass_startup; master->pub.finish_pass = finish_pass; master_selection(cinfo); } \ No newline at end of file diff --git a/Independent JPEG Group/jcomapi.c b/Independent JPEG Group/jcomapi.c new file mode 100644 index 0000000..71222e6 --- /dev/null +++ b/Independent JPEG Group/jcomapi.c @@ -0,0 +1 @@ +/* * jcomapi.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface routines that are used for both * compression and decompression. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Abort processing of a JPEG compression or decompression operation, * but don't destroy the object itself. * * For this, we merely clean up all the nonpermanent memory pools. * Note that temp files (virtual arrays) are not allowed to belong to * the permanent pool, so we will be able to close all temp files here. * Closing a data source or destination, if necessary, is the application's * responsibility. */ GLOBAL void jpeg_abort (j_common_ptr cinfo) { int pool; /* Releasing pools in reverse order might help avoid fragmentation * with some (brain-damaged) malloc libraries. */ for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { (*cinfo->mem->free_pool) (cinfo, pool); } /* Reset overall state for possible reuse of object */ cinfo->global_state = (cinfo->is_decompressor ? DSTATE_START : CSTATE_START); } /* * Destruction of a JPEG object. * * Everything gets deallocated except the master jpeg_compress_struct itself * and the error manager struct. Both of these are supplied by the application * and must be freed, if necessary, by the application. (Often they are on * the stack and so don't need to be freed anyway.) * Closing a data source or destination, if necessary, is the application's * responsibility. */ GLOBAL void jpeg_destroy (j_common_ptr cinfo) { /* We need only tell the memory manager to release everything. */ /* NB: mem pointer is NULL if memory mgr failed to initialize. */ if (cinfo->mem != NULL) (*cinfo->mem->self_destruct) (cinfo); cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */ cinfo->global_state = 0; /* mark it destroyed */ } /* * Allocate quantization and Huffman tables. For convenience, these are * always made large enough to hold any variant we might want. * (Would jutils.c be a more reasonable place to put these?) */ GLOBAL JQUANT_TBL * jpeg_alloc_quant_table (j_common_ptr cinfo) { JQUANT_TBL *tbl; typedef union { JCQUANT_TBL cquant; JDQUANT_TBL dquant; } ANY_QUANT_TBL; tbl = (JQUANT_TBL *) (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(ANY_QUANT_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } GLOBAL JHUFF_TBL * jpeg_alloc_huff_table (j_common_ptr cinfo) { JHUFF_TBL *tbl; typedef union { JCHUFF_TBL chuff; JDHUFF_TBL dhuff; } ANY_HUFF_TBL; tbl = (JHUFF_TBL *) (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(ANY_HUFF_TBL)); tbl->sent_table = FALSE; /* make sure this is false in any new table */ return tbl; } \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.auto b/Independent JPEG Group/jconfig.auto new file mode 100644 index 0000000..704abda --- /dev/null +++ b/Independent JPEG Group/jconfig.auto @@ -0,0 +1 @@ +/* jconfig.auto --- source file edited by configure script */ /* see jconfig.doc for explanations */ #undef HAVE_PROTOTYPES #undef HAVE_UNSIGNED_CHAR #undef HAVE_UNSIGNED_SHORT #undef void #undef const #undef CHAR_IS_UNSIGNED #undef HAVE_STDDEF_H #undef HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #undef NEED_FAR_POINTERS #undef NEED_SHORT_EXTERNAL_NAMES /* Define this if you get warnings about undefined structures. */ #undef INCOMPLETE_TYPES_BROKEN #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #undef INLINE /* These are for configuring the JPEG memory manager. */ #undef DEFAULT_MAX_MEM #undef NO_MKTEMP #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #undef TWO_FILE_COMMANDLINE #undef NEED_SIGNAL_CATCHER #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.bcc b/Independent JPEG Group/jconfig.bcc new file mode 100644 index 0000000..e1da499 --- /dev/null +++ b/Independent JPEG Group/jconfig.bcc @@ -0,0 +1 @@ +/* jconfig.bcc --- jconfig.h for Borland C (Turbo C) on MS-DOS. */ /* see jconfig.doc for explanations */ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* #define void char */ /* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #define NEED_FAR_POINTERS /* for small or medium memory model */ #undef NEED_SHORT_EXTERNAL_NAMES #define INCOMPLETE_TYPES_BROKEN /* suppress undefined-structure warnings */ #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ #define USE_FMEM /* Borland has _fmemcpy() and _fmemset() */ #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #define TWO_FILE_COMMANDLINE #define USE_SETMODE /* Borland has setmode() */ #define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ #undef DONT_USE_B_MODE #undef PROGRESS_REPORT /* optional */ #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.doc b/Independent JPEG Group/jconfig.doc new file mode 100644 index 0000000..e6f6b63 --- /dev/null +++ b/Independent JPEG Group/jconfig.doc @@ -0,0 +1 @@ +/* * jconfig.doc * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file documents the configuration options that are required to * customize the JPEG software for a particular system. * * The actual configuration options for a particular installation are stored * in jconfig.h. On many machines, jconfig.h can be generated automatically * or copied from one of the "canned" jconfig files that we supply. But if * you need to generate a jconfig.h file by hand, this file tells you how. * * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. * EDIT A COPY NAMED JCONFIG.H. */ /* * These symbols indicate the properties of your machine or compiler. * #define the symbol if yes, #undef it if no. */ /* Does your compiler support function prototypes? * (If not, you also need to use ansi2knr, see install.doc) */ #define HAVE_PROTOTYPES /* Does your compiler support the declaration "unsigned char" ? * How about "unsigned short" ? */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define "const" as empty if your compiler doesn't know the "const" keyword. */ /* #define const */ /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. */ #undef CHAR_IS_UNSIGNED /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDDEF_H /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDLIB_H /* Define this if your system does not have an ANSI/SysV , * but does have a BSD-style . */ #undef NEED_BSD_STRINGS /* Define this if your system does not provide typedef size_t in any of the * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in * instead. */ #undef NEED_SYS_TYPES_H /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #undef NEED_FAR_POINTERS /* Define this if your linker needs global names to be unique in less * than the first 15 characters. */ #undef NEED_SHORT_EXTERNAL_NAMES /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you * actually get "missing structure definition" warnings or errors while * compiling the JPEG code. */ #undef INCOMPLETE_TYPES_BROKEN /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS has been defined. */ #ifdef JPEG_INTERNALS /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ /* * The remaining options do not affect the JPEG library proper, * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). * Other applications can ignore these. */ #ifdef JPEG_CJPEG_DJPEG /* These defines indicate which image (non-JPEG) file formats are allowed. */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of cjpeg.c or djpeg.c. */ #undef TWO_FILE_COMMANDLINE /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #undef NEED_SIGNAL_CATCHER /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.h b/Independent JPEG Group/jconfig.h new file mode 100644 index 0000000..e6f6b63 --- /dev/null +++ b/Independent JPEG Group/jconfig.h @@ -0,0 +1 @@ +/* * jconfig.doc * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file documents the configuration options that are required to * customize the JPEG software for a particular system. * * The actual configuration options for a particular installation are stored * in jconfig.h. On many machines, jconfig.h can be generated automatically * or copied from one of the "canned" jconfig files that we supply. But if * you need to generate a jconfig.h file by hand, this file tells you how. * * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. * EDIT A COPY NAMED JCONFIG.H. */ /* * These symbols indicate the properties of your machine or compiler. * #define the symbol if yes, #undef it if no. */ /* Does your compiler support function prototypes? * (If not, you also need to use ansi2knr, see install.doc) */ #define HAVE_PROTOTYPES /* Does your compiler support the declaration "unsigned char" ? * How about "unsigned short" ? */ #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* Define "void" as "char" if your compiler doesn't know about type void. * NOTE: be sure to define void such that "void *" represents the most general * pointer type, e.g., that returned by malloc(). */ /* #define void char */ /* Define "const" as empty if your compiler doesn't know the "const" keyword. */ /* #define const */ /* Define this if an ordinary "char" type is unsigned. * If you're not sure, leaving it undefined will work at some cost in speed. * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. */ #undef CHAR_IS_UNSIGNED /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDDEF_H /* Define this if your system has an ANSI-conforming file. */ #define HAVE_STDLIB_H /* Define this if your system does not have an ANSI/SysV , * but does have a BSD-style . */ #undef NEED_BSD_STRINGS /* Define this if your system does not provide typedef size_t in any of the * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in * instead. */ #undef NEED_SYS_TYPES_H /* For 80x86 machines, you need to define NEED_FAR_POINTERS, * unless you are using a large-data memory model or 80386 flat-memory mode. * On less brain-damaged CPUs this symbol must not be defined. * (Defining this symbol causes large data structures to be referenced through * "far" pointers and to be allocated with a special version of malloc.) */ #undef NEED_FAR_POINTERS /* Define this if your linker needs global names to be unique in less * than the first 15 characters. */ #undef NEED_SHORT_EXTERNAL_NAMES /* Although a real ANSI C compiler can deal perfectly well with pointers to * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI * and pseudo-ANSI compilers get confused. To keep one of these bozos happy, * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you * actually get "missing structure definition" warnings or errors while * compiling the JPEG code. */ #undef INCOMPLETE_TYPES_BROKEN /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS has been defined. */ #ifdef JPEG_INTERNALS /* Define this if your compiler implements ">>" on signed values as a logical * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, * which is the normal and rational definition. */ #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ /* * The remaining options do not affect the JPEG library proper, * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). * Other applications can ignore these. */ #ifdef JPEG_CJPEG_DJPEG /* These defines indicate which image (non-JPEG) file formats are allowed. */ #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ /* Define this if you want to name both input and output files on the command * line, rather than using stdout and optionally stdin. You MUST do this if * your system can't cope with binary I/O to stdin/stdout. See comments at * head of cjpeg.c or djpeg.c. */ #undef TWO_FILE_COMMANDLINE /* Define this if your system needs explicit cleanup of temporary files. * This is crucial under MS-DOS, where the temporary "files" may be areas * of extended memory; on most other systems it's not as important. */ #undef NEED_SIGNAL_CATCHER /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). * This is necessary on systems that distinguish text files from binary files, * and is harmless on most systems that don't. If you have one of the rare * systems that complains about the "b" spec, define this symbol. */ #undef DONT_USE_B_MODE /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ #undef PROGRESS_REPORT #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.manx b/Independent JPEG Group/jconfig.manx new file mode 100644 index 0000000..98533b9 --- /dev/null +++ b/Independent JPEG Group/jconfig.manx @@ -0,0 +1 @@ +/* jconfig.manx --- jconfig.h for Amiga systems using Manx Aztec C ver 5.x. */ /* see jconfig.doc for explanations */ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* #define void char */ /* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #undef NEED_FAR_POINTERS #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ #define SHORTxSHORT_32 /* produces better DCT code with Aztec C */ #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #define TWO_FILE_COMMANDLINE #define NEED_SIGNAL_CATCHER #undef DONT_USE_B_MODE #undef PROGRESS_REPORT /* optional */ #define signal_catcher _abort /* hack for Aztec C naming requirements */ #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.mc6 b/Independent JPEG Group/jconfig.mc6 new file mode 100644 index 0000000..6b2e554 --- /dev/null +++ b/Independent JPEG Group/jconfig.mc6 @@ -0,0 +1 @@ +/* jconfig.mc6 --- jconfig.h for Microsoft C on MS-DOS, version 6.00A & up. */ /* see jconfig.doc for explanations */ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* #define void char */ /* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #define NEED_FAR_POINTERS /* for small or medium memory model */ #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #define USE_MSDOS_MEMMGR /* Define this if you use jmemdos.c */ #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */ #define USE_FMEM /* Microsoft has _fmemcpy() and _fmemset() */ #define NEED_FHEAPMIN /* far heap management routines are broken */ #define SHORTxLCONST_32 /* enable compiler-specific DCT optimization */ /* Note: the above define is known to improve the code with Microsoft C 6.00A. * I do not know whether it is good for later compiler versions. * Please report any info on this point to jpeg-info@uunet.uu.net. */ #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #define TWO_FILE_COMMANDLINE #define USE_SETMODE /* Microsoft has setmode() */ #define NEED_SIGNAL_CATCHER /* Define this if you use jmemdos.c */ #undef DONT_USE_B_MODE #undef PROGRESS_REPORT /* optional */ #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.sas b/Independent JPEG Group/jconfig.sas new file mode 100644 index 0000000..01d31ed --- /dev/null +++ b/Independent JPEG Group/jconfig.sas @@ -0,0 +1 @@ +/* jconfig.sas --- jconfig.h for Amiga systems using SAS C 6.0 and up. */ /* see jconfig.doc for explanations */ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* #define void char */ /* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #undef NEED_FAR_POINTERS #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #define TEMP_DIRECTORY "JPEGTMP:" /* recommended setting for Amiga */ #define NO_MKTEMP /* SAS C doesn't have mktemp() */ #define SHORTxSHORT_32 /* produces better DCT code with SAS C */ #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #define TWO_FILE_COMMANDLINE #define NEED_SIGNAL_CATCHER #undef DONT_USE_B_MODE #undef PROGRESS_REPORT /* optional */ #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.st b/Independent JPEG Group/jconfig.st new file mode 100644 index 0000000..9c8021a --- /dev/null +++ b/Independent JPEG Group/jconfig.st @@ -0,0 +1 @@ +/* jconfig.st --- jconfig.h for Atari ST/STE/TT using Pure C or Turbo C. */ /* see jconfig.doc for explanations */ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* #define void char */ /* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #undef NEED_FAR_POINTERS #undef NEED_SHORT_EXTERNAL_NAMES #define INCOMPLETE_TYPES_BROKEN /* suppress undefined-structure warnings */ #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #define TWO_FILE_COMMANDLINE /* optional -- undef if you like Unix style */ #define NEED_SIGNAL_CATCHER /* needed if you use jmemname.c */ #undef DONT_USE_B_MODE #undef PROGRESS_REPORT /* optional */ #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jconfig.vms b/Independent JPEG Group/jconfig.vms new file mode 100644 index 0000000..29be704 --- /dev/null +++ b/Independent JPEG Group/jconfig.vms @@ -0,0 +1 @@ +/* jconfig.vms --- jconfig.h for use on VAX VMS. */ /* see jconfig.doc for explanations */ #define HAVE_PROTOTYPES #define HAVE_UNSIGNED_CHAR #define HAVE_UNSIGNED_SHORT /* #define void char */ /* #define const */ #undef CHAR_IS_UNSIGNED #define HAVE_STDDEF_H #define HAVE_STDLIB_H #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #undef NEED_FAR_POINTERS #undef NEED_SHORT_EXTERNAL_NAMES #undef INCOMPLETE_TYPES_BROKEN #ifdef JPEG_INTERNALS #undef RIGHT_SHIFT_IS_UNSIGNED #endif /* JPEG_INTERNALS */ #ifdef JPEG_CJPEG_DJPEG #define GIF_SUPPORTED /* GIF image file format */ #define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */ #undef RLE_SUPPORTED /* Utah RLE image file format */ #define TARGA_SUPPORTED /* Targa image file format */ #define TWO_FILE_COMMANDLINE /* Needed on VMS */ #undef NEED_SIGNAL_CATCHER #undef DONT_USE_B_MODE #undef PROGRESS_REPORT /* optional */ #endif /* JPEG_CJPEG_DJPEG */ \ No newline at end of file diff --git a/Independent JPEG Group/jcparam.c b/Independent JPEG Group/jcparam.c new file mode 100644 index 0000000..7a08bb0 --- /dev/null +++ b/Independent JPEG Group/jcparam.c @@ -0,0 +1 @@ +/* * jcparam.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains optional default-setting code for the JPEG compressor. * Applications do not have to use this file, but those that don't use it * must know a lot more about the innards of the JPEG code. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Quantization table setup routines */ GLOBAL void jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline) /* Define a quantization table equal to the basic_table times * a scale factor (given as a percentage). * If force_baseline is TRUE, the computed quantization table entries * are limited to 1..255 for JPEG baseline compatibility. */ { JQUANT_TBL ** qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; int i; long temp; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); if (*qtblptr == NULL) *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); for (i = 0; i < DCTSIZE2; i++) { temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; /* limit the values to the valid range */ if (temp <= 0L) temp = 1L; #if BITS_IN_JSAMPLE == 8 if (temp > 32767L) temp = 32767L; /* limit quant vals to 'short' */ #else if (temp > 65535L) temp = 65535L; /* quant vals are 'UINT16' */ #endif if (force_baseline && temp > 255L) temp = 255L; /* limit to baseline range if requested */ (*qtblptr)->quantval[i] = (UINT16) temp; } /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*qtblptr)->sent_table = FALSE; } GLOBAL void jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables * and a straight percentage-scaling quality scale. In most cases it's better * to use jpeg_set_quality (below); this entry point is provided for * applications that insist on a linear percentage scaling. */ { /* This is the sample quantization table given in the JPEG spec section K.1, * but expressed in zigzag order (as are all of our quant. tables). * The spec says that the values given produce "good" quality, and * when divided by 2, "very good" quality. */ static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101, 103, 99 }; static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; /* Set up two quantization tables using the specified scaling */ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, scale_factor, force_baseline); jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, scale_factor, force_baseline); } GLOBAL int jpeg_quality_scaling (int quality) /* Convert a user-specified quality rating to a percentage scaling factor * for an underlying quantization table, using our recommended scaling curve. * The input 'quality' factor should be 0 (terrible) to 100 (very good). */ { /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */ if (quality <= 0) quality = 1; if (quality > 100) quality = 100; /* The basic table is used as-is (scaling 100) for a quality of 50. * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; * note that at Q=100 the scaling is 0, which will cause j_add_quant_table * to make all the table entries 1 (hence, no quantization loss). * Qualities 1..50 are converted to scaling percentage 5000/Q. */ if (quality < 50) quality = 5000 / quality; else quality = 200 - quality*2; return quality; } GLOBAL void jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) /* Set or change the 'quality' (quantization) setting, using default tables. * This is the standard quality-adjusting entry point for typical user * interfaces; only those who want detailed control over quantization tables * would use the preceding three routines directly. */ { /* Convert user 0-100 rating to percentage scaling */ quality = jpeg_quality_scaling(quality); /* Set up standard quality tables */ jpeg_set_linear_quality(cinfo, quality, force_baseline); } /* * Huffman table setup routines */ LOCAL void add_huff_table (j_compress_ptr cinfo, JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) /* Define a Huffman table */ { if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); MEMCOPY((*htblptr)->huffval, val, SIZEOF((*htblptr)->huffval)); /* Initialize sent_table FALSE so table will be written to JPEG file. */ (*htblptr)->sent_table = FALSE; } LOCAL void std_huff_tables (j_compress_ptr cinfo) /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ /* IMPORTANT: these are only valid for 8-bit data precision! */ { static const UINT8 bits_dc_luminance[17] = { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_luminance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_dc_chrominance[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static const UINT8 val_dc_chrominance[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static const UINT8 bits_ac_luminance[17] = { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; static const UINT8 val_ac_luminance[] = { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; static const UINT8 bits_ac_chrominance[17] = { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; static const UINT8 val_ac_chrominance[] = { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa }; add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], bits_dc_luminance, val_dc_luminance); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], bits_ac_luminance, val_ac_luminance); add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], bits_dc_chrominance, val_dc_chrominance); add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], bits_ac_chrominance, val_ac_chrominance); } /* * Default parameter setup for compression. * * Applications that don't choose to use this routine must do their * own setup of all these parameters. Alternately, you can call this * to establish defaults and then alter parameters selectively. This * is the recommended approach since, if we add any new parameters, * your code will still work (they'll be set to reasonable defaults). */ GLOBAL void jpeg_set_defaults (j_compress_ptr cinfo) { int i; /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Allocate comp_info array large enough for maximum component count. * Array is made permanent in case application wants to compress * multiple images at same param settings. */ if (cinfo->comp_info == NULL) cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, MAX_COMPONENTS * SIZEOF(jpeg_component_info)); /* Initialize everything not dependent on the color space */ cinfo->data_precision = BITS_IN_JSAMPLE; /* Set up two quantization tables using default quality of 75 */ jpeg_set_quality(cinfo, 75, TRUE); /* Set up two Huffman tables */ std_huff_tables(cinfo); /* Initialize default arithmetic coding conditioning */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } /* Use Huffman coding, not arithmetic coding, by default */ cinfo->arith_code = FALSE; /* Color images are interleaved by default */ cinfo->interleave = TRUE; /* By default, don't do extra passes to optimize entropy coding */ cinfo->optimize_coding = FALSE; /* The standard Huffman tables are only valid for 8-bit data precision. * If the precision is higher, force optimization on so that usable * tables will be computed. This test can be removed if default tables * are supplied that are valid for the desired precision. */ if (cinfo->data_precision > 8) cinfo->optimize_coding = TRUE; /* By default, use the simpler non-cosited sampling alignment */ cinfo->CCIR601_sampling = FALSE; /* No input smoothing */ cinfo->smoothing_factor = 0; /* No restart markers */ cinfo->restart_interval = 0; cinfo->restart_in_rows = 0; cinfo->write_JFIF_header = TRUE; /* write a JFIF marker */ cinfo->density_unit = 0; /* Pixel size is unknown by default */ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */ cinfo->Y_density = 1; cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ /* Choose JPEG colorspace based on input space, set defaults accordingly */ switch (cinfo->in_color_space) { case JCS_GRAYSCALE: jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); break; case JCS_RGB: jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_YCbCr: jpeg_set_colorspace(cinfo, JCS_YCbCr); break; case JCS_CMYK: jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ break; case JCS_YCCK: jpeg_set_colorspace(cinfo, JCS_YCCK); break; case JCS_UNKNOWN: jpeg_set_colorspace(cinfo, JCS_UNKNOWN); break; default: ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); } } /* * Set the JPEG colorspace, and choose colorspace-dependent default values. */ GLOBAL void jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) { jpeg_component_info * compptr; int ci; #define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \ (compptr = &cinfo->comp_info[index], \ compptr->component_index = (index), \ compptr->component_id = (id), \ compptr->h_samp_factor = (hsamp), \ compptr->v_samp_factor = (vsamp), \ compptr->quant_tbl_no = (quant), \ compptr->dc_tbl_no = (dctbl), \ compptr->ac_tbl_no = (actbl) ) /* Safety check to ensure start_compress not called yet. */ if (cinfo->global_state != CSTATE_START) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* For all colorspaces, we use Q and Huff tables 0 for luminance components, * tables 1 for chrominance components. */ cinfo->jpeg_color_space = colorspace; cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ switch (colorspace) { case JCS_GRAYSCALE: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 1; /* JFIF specifies component ID 1 */ SET_COMP(0, 1, 1,1, 0, 0,0); break; case JCS_RGB: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ cinfo->num_components = 3; SET_COMP(0, 'R', 1,1, 0, 0,0); SET_COMP(1, 'G', 1,1, 0, 0,0); SET_COMP(2, 'B', 1,1, 0, 0,0); break; case JCS_YCbCr: cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ cinfo->num_components = 3; /* JFIF specifies component IDs 1,2,3 */ /* We default to 2x2 subsamples of chrominance */ SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(2, 3, 1,1, 1, 1,1); break; case JCS_CMYK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ cinfo->num_components = 4; SET_COMP(0, 'C', 1,1, 0, 0,0); SET_COMP(1, 'M', 1,1, 0, 0,0); SET_COMP(2, 'Y', 1,1, 0, 0,0); SET_COMP(3, 'K', 1,1, 0, 0,0); break; case JCS_YCCK: cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ cinfo->num_components = 4; SET_COMP(0, 1, 2,2, 0, 0,0); SET_COMP(1, 2, 1,1, 1, 1,1); SET_COMP(2, 3, 1,1, 1, 1,1); SET_COMP(3, 4, 2,2, 0, 0,0); break; case JCS_UNKNOWN: cinfo->num_components = cinfo->input_components; if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); for (ci = 0; ci < cinfo->num_components; ci++) { SET_COMP(ci, ci, 1,1, 0, 0,0); } break; default: ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); } } \ No newline at end of file diff --git a/Independent JPEG Group/jcprepct.c b/Independent JPEG Group/jcprepct.c new file mode 100644 index 0000000..8e79bd7 --- /dev/null +++ b/Independent JPEG Group/jcprepct.c @@ -0,0 +1 @@ +/* * jcprepct.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the compression preprocessing controller. * This controller manages the color conversion, downsampling, * and edge expansion steps. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private buffer controller object */ typedef struct { struct jpeg_c_prep_controller pub; /* public fields */ /* Downsampling input buffer. This buffer holds color-converted data * until we have enough to do a downsample step. */ JSAMPARRAY color_buf[MAX_COMPONENTS]; int rows_in_buf; /* counts rows stored in color_buf */ JDIMENSION rows_to_go; /* counts rows remaining in source image */ } my_prep_controller; typedef my_prep_controller * my_prep_ptr; /* * Initialize for a processing pass. */ METHODDEF void start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; switch (pass_mode) { case JBUF_PASS_THRU: break; default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } /* Mark the conversion buffer empty */ prep->rows_in_buf = 0; /* Initialize total-height counter for detecting bottom of image */ prep->rows_to_go = cinfo->image_height; } /* * Expand an image vertically from height input_rows to height output_rows, * by duplicating the bottom row. */ LOCAL void expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, int input_rows, int output_rows) { register int row; for (row = input_rows; row < output_rows; row++) { jcopy_sample_rows(image_data, input_rows-1, image_data, row, 1, num_cols); } } /* * Process some data. * * Preprocessor output data is counted in "row groups". A row group * is defined to be v_samp_factor sample rows of each component. * Downsampling will produce this much data from each max_v_samp_factor * input rows. */ METHODDEF void pre_process_data (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail) { my_prep_ptr prep = (my_prep_ptr) cinfo->prep; int numrows, ci; JDIMENSION inrows; jpeg_component_info * compptr; while (*in_row_ctr < in_rows_avail && *out_row_group_ctr < out_row_groups_avail) { /* Do color conversion to fill the conversion buffer. */ inrows = in_rows_avail - *in_row_ctr; numrows = cinfo->max_v_samp_factor - prep->rows_in_buf; numrows = (int) MIN((JDIMENSION) numrows, inrows); (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, prep->color_buf, (JDIMENSION) prep->rows_in_buf, numrows); *in_row_ctr += numrows; prep->rows_in_buf += numrows; prep->rows_to_go -= numrows; /* If at bottom of image, pad to fill the conversion buffer. */ if (prep->rows_to_go == 0 && prep->rows_in_buf < cinfo->max_v_samp_factor) { for (ci = 0; ci < cinfo->num_components; ci++) { expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, prep->rows_in_buf, cinfo->max_v_samp_factor); } prep->rows_in_buf = cinfo->max_v_samp_factor; } /* If we've filled the conversion buffer, empty it. */ if (prep->rows_in_buf == cinfo->max_v_samp_factor) { (*cinfo->downsample->downsample) (cinfo, prep->color_buf, output_buf, *out_row_group_ctr); prep->rows_in_buf = 0; (*out_row_group_ctr)++; } /* If at bottom of image, pad the output to a full MCU height. * Note we assume the caller is providing a one-MCU-height output buffer! */ if (prep->rows_to_go == 0 && *out_row_group_ctr < out_row_groups_avail) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { expand_bottom_edge(output_buf[ci], compptr->width_in_blocks * DCTSIZE, (int) (*out_row_group_ctr * compptr->v_samp_factor), (int) (out_row_groups_avail * compptr->v_samp_factor)); } *out_row_group_ctr = out_row_groups_avail; break; /* can exit outer loop without test */ } } } /* * Initialize preprocessing controller. */ GLOBAL void jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) { my_prep_ptr prep; int ci; jpeg_component_info * compptr; prep = (my_prep_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_prep_controller)); cinfo->prep = (struct jpeg_c_prep_controller *) prep; prep->pub.start_pass = start_pass; prep->pub.pre_process_data = pre_process_data; /* Allocate the color conversion buffer. * We allocate enough storage to allow downsampler to edge-expand in this * buffer, if it so chooses. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * cinfo->max_h_samp_factor) / compptr->h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } } \ No newline at end of file diff --git a/Independent JPEG Group/jcsample.c b/Independent JPEG Group/jcsample.c new file mode 100644 index 0000000..7e74f13 --- /dev/null +++ b/Independent JPEG Group/jcsample.c @@ -0,0 +1 @@ +/* * jcsample.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains downsampling routines. * * Downsampling input data is counted in "row groups". A row group * is defined to be max_v_samp_factor pixel rows of each component, * from which the downsampler produces v_samp_factor sample rows. * A single row group is processed in each call to the downsampler module. * * The downsampler is responsible for edge-expansion of its output data * to fill an integral number of DCT blocks horizontally. The source buffer * may be modified if it is helpful for this purpose (the source buffer is * allocated wide enough to correspond to the desired output width). * The caller (the prep controller) is responsible for vertical padding. * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. * * The downsampling algorithm used here is a simple average of the source * pixels covered by the output pixel. The hi-falutin sampling literature * refers to this as a "box filter". In general the characteristics of a box * filter are not very good, but for the specific cases we normally use (1:1 * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not * nearly so bad. If you intend to use other sampling ratios, you'd be well * advised to improve this code. * * A simple input-smoothing capability is provided. This is mainly intended * for cleaning up color-dithered GIF input files (if you find it inadequate, * we suggest using an external filtering program such as pnmconvol). When * enabled, each input pixel P is replaced by a weighted sum of itself and its * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF, * where SF = (smoothing_factor / 1024). * Currently, smoothing is only supported for 2h2v sampling factors. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #undef INPUT_SMOOTHING_SUPPORTED /* for now */ /* Input smoothing is currently unsupported since jcprepct.c doesn't * yet handle creation of context rows for downsampling. */ /* Pointer to routine to downsample a single component */ typedef JMETHOD(void, downsample1_ptr, (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data)); /* Private subobject */ typedef struct { struct jpeg_downsampler pub; /* public fields */ /* Downsampling method pointers, one per component */ downsample1_ptr methods[MAX_COMPONENTS]; } my_downsampler; typedef my_downsampler * my_downsample_ptr; /* * Initialize for a downsampling pass. */ METHODDEF void start_pass (j_compress_ptr cinfo) { /* no work for now */ } /* * Expand a component horizontally from width input_cols to width output_cols, * by duplicating the rightmost samples. */ LOCAL void expand_right_edge (JSAMPARRAY image_data, int num_rows, JDIMENSION input_cols, JDIMENSION output_cols) { register JSAMPROW ptr; register JSAMPLE pixval; register int count; register int row; int numcols = (int) (output_cols - input_cols); if (numcols > 0) { for (row = 0; row < num_rows; row++) { ptr = image_data[row] + (input_cols-1); pixval = GETJSAMPLE(*ptr++); for (count = numcols; count > 0; count--) *ptr++ = pixval; } } } /* * Do downsampling for a whole row group (all components). * * In this version we simply downsample each component independently. */ METHODDEF void sep_downsample (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) { my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; int ci; jpeg_component_info * compptr; JSAMPARRAY out_ptr; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); (*downsample->methods[ci]) (cinfo, compptr, input_buf[ci], out_ptr); } } /* * Downsample pixel values of a single component. * One row group is processed per call. * This version handles arbitrary integral sampling ratios, without smoothing. * Note that this version is not actually used for customary sampling ratios. */ METHODDEF void int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */ JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; JSAMPROW inptr, outptr; INT32 outvalue; h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; numpix = h_expand * v_expand; numpix2 = numpix/2; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * h_expand); inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; for (outcol = 0, outcol_h = 0; outcol < output_cols; outcol++, outcol_h += h_expand) { outvalue = 0; for (v = 0; v < v_expand; v++) { inptr = input_data[inrow+v] + outcol_h; for (h = 0; h < h_expand; h++) { outvalue += (INT32) GETJSAMPLE(*inptr++); } } *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); } inrow += v_expand; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * without smoothing. */ METHODDEF void fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { /* Copy the data */ jcopy_sample_rows(input_data, 0, output_data, 0, cinfo->max_v_samp_factor, cinfo->image_width); /* Edge-expand */ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width, compptr->width_in_blocks * DCTSIZE); } /* * Downsample pixel values of a single component. * This version handles the common case of 2:1 horizontal and 1:1 vertical, * without smoothing. * * A note about the "bias" calculations: when rounding fractional values to * integer, we do not want to always round 0.5 up to the next integer. * If we did that, we'd introduce a noticeable bias towards larger values. * Instead, this code is arranged so that 0.5 will be rounded up or down at * alternate pixel locations (a simple ordered dither pattern). */ METHODDEF void h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int outrow; JDIMENSION outcol; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr, outptr; register int bias; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; bias = 0; /* bias = 0,1,0,1,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) + bias) >> 1); bias ^= 1; /* 0=>1, 1=>0 */ inptr += 2; } } } /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * without smoothing. */ METHODDEF void h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION outcol; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr0, inptr1, outptr; register int bias; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data, cinfo->max_v_samp_factor, cinfo->image_width, output_cols * 2); inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; bias = 1; /* bias = 1,2,1,2,... for successive samples */ for (outcol = 0; outcol < output_cols; outcol++) { *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) + bias) >> 2); bias ^= 3; /* 1=>2, 2=>1 */ inptr0 += 2; inptr1 += 2; } inrow += 2; } } #ifdef INPUT_SMOOTHING_SUPPORTED /* * Downsample pixel values of a single component. * This version handles the standard case of 2:1 horizontal and 2:1 vertical, * with smoothing. */ METHODDEF void h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int inrow, outrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols * 2); /* We don't bother to form the individual "smoothed" input pixel values; * we can directly compute the output which is the average of the four * smoothed values. Each of the four member pixels contributes a fraction * (1-8*SF) to its own smoothed image and a fraction SF to each of the three * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final * output. The four corner-adjacent neighbor pixels contribute a fraction * SF to just one smoothed pixel, or SF/4 to the final output; while the * eight edge-adjacent neighbors contribute SF to each of two smoothed * pixels, or SF/2 overall. In order to use integer arithmetic, these * factors are scaled by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ inrow = 0; for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr0 = input_data[inrow]; inptr1 = input_data[inrow+1]; above_ptr = input_data[inrow-1]; below_ptr = input_data[inrow+2]; /* Special case for first column: pretend column -1 is same as column 0 */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); neighsum += neighsum; neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; for (colctr = output_cols - 2; colctr > 0; colctr--) { /* sum of pixels directly mapped to this output element */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); /* sum of edge-neighbor pixels */ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); /* The edge-neighbors count twice as much as corner-neighbors */ neighsum += neighsum; /* Add in the corner-neighbors */ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); /* form final output scaled up by 2^16 */ membersum = membersum * memberscale + neighsum * neighscale; /* round, descale and output it */ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); neighsum += neighsum; neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768) >> 16); inrow += 2; } } /* * Downsample pixel values of a single component. * This version handles the special case of a full-size component, * with smoothing. */ METHODDEF void fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, JSAMPARRAY input_data, JSAMPARRAY output_data) { int outrow; JDIMENSION colctr; JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; register JSAMPROW inptr, above_ptr, below_ptr, outptr; INT32 membersum, neighsum, memberscale, neighscale; int colsum, lastcolsum, nextcolsum; /* Expand input data enough to let all the output samples be generated * by the standard loop. Special-casing padded output would be more * efficient. */ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, cinfo->image_width, output_cols); /* Each of the eight neighbor pixels contributes a fraction SF to the * smoothed pixel, while the main pixel contributes (1-8*SF). In order * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. * Also recall that SF = smoothing_factor / 1024. */ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { outptr = output_data[outrow]; inptr = input_data[outrow]; above_ptr = input_data[outrow-1]; below_ptr = input_data[outrow+1]; /* Special case for first column */ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + GETJSAMPLE(*inptr); membersum = GETJSAMPLE(*inptr++); nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = colsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; for (colctr = output_cols - 2; colctr > 0; colctr--) { membersum = GETJSAMPLE(*inptr++); above_ptr++; below_ptr++; nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + nextcolsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); lastcolsum = colsum; colsum = nextcolsum; } /* Special case for last column */ membersum = GETJSAMPLE(*inptr); neighsum = lastcolsum + (colsum - membersum) + colsum; membersum = membersum * memberscale + neighsum * neighscale; *outptr = (JSAMPLE) ((membersum + 32768) >> 16); } } #endif /* INPUT_SMOOTHING_SUPPORTED */ /* * Module initialization routine for downsampling. * Note that we must select a routine for each component. */ GLOBAL void jinit_downsampler (j_compress_ptr cinfo) { my_downsample_ptr downsample; int ci; jpeg_component_info * compptr; boolean smoothok = TRUE; downsample = (my_downsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_downsampler)); cinfo->downsample = (struct jpeg_downsampler *) downsample; downsample->pub.start_pass = start_pass; downsample->pub.downsample = sep_downsample; downsample->pub.need_context_rows = FALSE; if (cinfo->CCIR601_sampling) ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); /* Verify we can handle the sampling factors, and set up method pointers */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = fullsize_smooth_downsample; downsample->pub.need_context_rows = TRUE; } else #endif downsample->methods[ci] = fullsize_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor == cinfo->max_v_samp_factor) { smoothok = FALSE; downsample->methods[ci] = h2v1_downsample; } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor) { downsample->methods[ci] = h2v2_smooth_downsample; downsample->pub.need_context_rows = TRUE; } else #endif downsample->methods[ci] = h2v2_downsample; } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { smoothok = FALSE; downsample->methods[ci] = int_downsample; } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); } #ifdef INPUT_SMOOTHING_SUPPORTED if (cinfo->smoothing_factor && !smoothok) TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); #endif } \ No newline at end of file diff --git a/Independent JPEG Group/jdapi.c b/Independent JPEG Group/jdapi.c new file mode 100644 index 0000000..5a8c62f --- /dev/null +++ b/Independent JPEG Group/jdapi.c @@ -0,0 +1 @@ +/* * jdapi.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains application interface code for the decompression half of * the JPEG library. Most of the routines intended to be called directly by * an application are in this file. But also see jcomapi.c for routines * shared by compression and decompression. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Initialization of a JPEG decompression object. * The error manager must already be set up (in case memory manager fails). */ GLOBAL void jpeg_create_decompress (j_decompress_ptr cinfo) { int i; /* For debugging purposes, zero the whole master structure. * But error manager pointer is already there, so save and restore it. */ { struct jpeg_error_mgr * err = cinfo->err; MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); cinfo->err = err; } cinfo->is_decompressor = TRUE; /* Initialize a memory manager instance for this object */ jinit_memory_mgr((j_common_ptr) cinfo); /* Zero out pointers to permanent structures. */ cinfo->progress = NULL; cinfo->src = NULL; for (i = 0; i < NUM_QUANT_TBLS; i++) cinfo->quant_tbl_ptrs[i] = NULL; for (i = 0; i < NUM_HUFF_TBLS; i++) { cinfo->dc_huff_tbl_ptrs[i] = NULL; cinfo->ac_huff_tbl_ptrs[i] = NULL; } cinfo->sample_range_limit = NULL; /* Initialize marker processor so application can override methods * for COM, APPn markers before calling jpeg_read_header. */ cinfo->marker = NULL; jinit_marker_reader(cinfo); /* OK, I'm ready */ cinfo->global_state = DSTATE_START; } /* * Destruction of a JPEG decompression object */ GLOBAL void jpeg_destroy_decompress (j_decompress_ptr cinfo) { jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ } /* * Set default decompression parameters. */ LOCAL void default_decompress_parms (j_decompress_ptr cinfo) { /* Guess the input colorspace, and set output colorspace accordingly. */ /* (Wish JPEG committee had provided a real way to specify this...) */ /* Note application may override our guesses. */ switch (cinfo->num_components) { case 1: cinfo->jpeg_color_space = JCS_GRAYSCALE; cinfo->out_color_space = JCS_GRAYSCALE; break; case 3: if (cinfo->saw_JFIF_marker) { cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ } else if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: cinfo->jpeg_color_space = JCS_RGB; break; case 1: cinfo->jpeg_color_space = JCS_YCbCr; break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ break; } } else { /* Saw no special markers, try to guess from the component IDs */ int cid0 = cinfo->comp_info[0].component_id; int cid1 = cinfo->comp_info[1].component_id; int cid2 = cinfo->comp_info[2].component_id; if (cid0 == 1 && cid1 == 2 && cid2 == 3) cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ else if (cid0 == 82 && cid1 == 71 && cid2 == 66) cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ else { TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ } } /* Always guess RGB is proper output colorspace. */ cinfo->out_color_space = JCS_RGB; break; case 4: if (cinfo->saw_Adobe_marker) { switch (cinfo->Adobe_transform) { case 0: cinfo->jpeg_color_space = JCS_CMYK; break; case 2: cinfo->jpeg_color_space = JCS_YCCK; break; default: WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ break; } } else { /* No special markers, assume straight CMYK. */ cinfo->jpeg_color_space = JCS_CMYK; } cinfo->out_color_space = JCS_CMYK; break; default: cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->out_color_space = JCS_UNKNOWN; break; } /* Set defaults for other decompression parameters. */ cinfo->scale_num = 1; /* 1:1 scaling */ cinfo->scale_denom = 1; cinfo->output_gamma = 1.0; cinfo->quantize_colors = FALSE; /* We set these in case application only sets quantize_colors. */ cinfo->two_pass_quantize = TRUE; cinfo->use_dithering = TRUE; cinfo->desired_number_of_colors = 256; cinfo->colormap = NULL; cinfo->do_block_smoothing = FALSE; cinfo->do_fancy_upsampling = TRUE; } /* * Decompression startup: read start of JPEG datastream to see what's there. * Need only initialize JPEG object and supply a data source before calling. * * This routine will read as far as the first SOS marker (ie, actual start of * compressed data), and will save all tables and parameters in the JPEG * object. It will also initialize the decompression parameters to default * values, and finally return JPEG_HEADER_OK. On return, the application may * adjust the decompression parameters and then call jpeg_start_decompress. * (Or, if the application only wanted to determine the image parameters, * the data need not be decompressed. In that case, call jpeg_abort or * jpeg_destroy to release any temporary space.) * If an abbreviated (tables only) datastream is presented, the routine will * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then * re-use the JPEG object to read the abbreviated image datastream(s). * It is unnecessary (but OK) to call jpeg_abort in this case. * The JPEG_SUSPENDED return code only occurs if the data source module * requests suspension of the decompressor. In this case the application * should load more source data and then re-call jpeg_read_header to resume * processing. * If a non-suspending data source is used and require_image is TRUE, then the * return code need not be inspected since only JPEG_HEADER_OK is possible. */ GLOBAL int jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) { int retcode; if (cinfo->global_state == DSTATE_START) { /* First-time actions: reset appropriate modules */ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); (*cinfo->marker->reset_marker_reader) (cinfo); (*cinfo->src->init_source) (cinfo); cinfo->global_state = DSTATE_INHEADER; } else if (cinfo->global_state != DSTATE_INHEADER) { ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } retcode = (*cinfo->marker->read_markers) (cinfo); switch (retcode) { case JPEG_HEADER_OK: /* Found SOS, prepare to decompress */ /* Set up default parameters based on header data */ default_decompress_parms(cinfo); /* Set global state: ready for start_decompress */ cinfo->global_state = DSTATE_READY; break; case JPEG_HEADER_TABLES_ONLY: /* Found EOI before any SOS */ if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_NO_SOS); if (require_image) /* Complain if application wants an image */ ERREXIT(cinfo, JERR_NO_IMAGE); /* We need not do any cleanup since only permanent storage (for DQT, DHT) * has been allocated. */ /* Set global state: ready for a new datastream */ cinfo->global_state = DSTATE_START; break; case JPEG_SUSPENDED: /* Had to suspend before end of headers */ /* no work */ break; } return retcode; } /* * Decompression initialization. * jpeg_read_header must be completed before calling this. * * If a multipass operating mode was selected, this will do all but the * last pass, and thus may take a great deal of time. */ GLOBAL void jpeg_start_decompress (j_decompress_ptr cinfo) { JDIMENSION row_ctr; if (cinfo->global_state != DSTATE_READY) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); /* Perform master selection of active modules */ jinit_master_decompress(cinfo); /* Do all but the final (output) pass, and set up for that one. */ for (;;) { (*cinfo->master->prepare_for_pass) (cinfo); if (cinfo->master->is_last_pass) break; /* loop counting here needs reworked for multiple-source-scan case??? */ cinfo->output_scanline = 0; while (cinfo->output_scanline < cinfo->output_height) { row_ctr = 0; (*cinfo->main->process_data) (cinfo, NULL, &row_ctr, (JDIMENSION) 0); if (row_ctr == 0) /* check for failure to make progress */ ERREXIT(cinfo, JERR_CANT_SUSPEND); cinfo->output_scanline += row_ctr; } (*cinfo->master->finish_pass) (cinfo); } /* Ready for application to drive last pass through jpeg_read_scanlines */ cinfo->output_scanline = 0; cinfo->global_state = DSTATE_SCANNING; } /* * Read some scanlines of data from the JPEG decompressor. * * The return value will be the number of lines actually read. * This may be less than the number requested in several cases, * including bottom of image, data source suspension, and operating * modes that emit multiple scanlines at a time. */ GLOBAL JDIMENSION jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines) { JDIMENSION row_ctr; if (cinfo->global_state != DSTATE_SCANNING) ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); row_ctr = 0; (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); cinfo->output_scanline += row_ctr; return row_ctr; } /* * Finish JPEG decompression. * * This will normally just verify the file trailer and release temp storage. * * Returns FALSE if suspended. The return value need be inspected only if * a suspending data source is used. */ GLOBAL boolean jpeg_finish_decompress (j_decompress_ptr cinfo) { if (cinfo->global_state == DSTATE_SCANNING && cinfo->output_scanline == cinfo->output_height) { /* Terminate final pass */ (*cinfo->master->finish_pass) (cinfo); cinfo->global_state = DSTATE_STOPPING; } else if (cinfo->global_state != DSTATE_STOPPING) { ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); } /* Check for EOI in source file, unless master control already read it */ if (! cinfo->master->eoi_processed) { switch ((*cinfo->marker->read_markers) (cinfo)) { case JPEG_HEADER_OK: /* Found SOS!? */ ERREXIT(cinfo, JERR_EOI_EXPECTED); break; case JPEG_HEADER_TABLES_ONLY: /* Found EOI, A-OK */ break; case JPEG_SUSPENDED: /* Suspend, come back later */ return FALSE; } } /* Do final cleanup */ (*cinfo->src->term_source) (cinfo); /* We can use jpeg_abort to release memory and reset global_state */ jpeg_abort((j_common_ptr) cinfo); return TRUE; } /* * Abort processing of a JPEG decompression operation, * but don't destroy the object itself. */ GLOBAL void jpeg_abort_decompress (j_decompress_ptr cinfo) { jpeg_abort((j_common_ptr) cinfo); /* use common routine */ } \ No newline at end of file diff --git a/Independent JPEG Group/jdatadst.c b/Independent JPEG Group/jdatadst.c new file mode 100644 index 0000000..8891d34 --- /dev/null +++ b/Independent JPEG Group/jdatadst.c @@ -0,0 +1 @@ +/* * jdatadst.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains compression data destination routines for the case of * emitting JPEG data to a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * destination manager. * IMPORTANT: we assume that fwrite() will correctly transcribe an array of * JOCTETs into 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* Expanded data destination object for stdio output */ typedef struct { struct jpeg_destination_mgr pub; /* public fields */ FILE * outfile; /* target stream */ JOCTET * buffer; /* start of buffer */ } my_destination_mgr; typedef my_destination_mgr * my_dest_ptr; #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ /* * Initialize destination --- called by jpeg_start_compress * before any data is actually written. */ METHODDEF void init_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; /* Allocate the output buffer --- it will be released when done with image */ dest->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; } /* * Empty the output buffer --- called whenever buffer fills up. * * In typical applications, this should write the entire output buffer * (ignoring the current state of next_output_byte & free_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been dumped. * * In applications that need to be able to suspend compression due to output * overrun, a FALSE return indicates that the buffer cannot be emptied now. * In this situation, the compressor will return to its caller (possibly with * an indication that it has not accepted all the supplied scanlines). The * application should resume compression after it has made more room in the * output buffer. Note that there are substantial restrictions on the use of * suspension --- see the documentation. * * When suspending, the compressor will back up to a convenient restart point * (typically the start of the current MCU). next_output_byte & free_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point will be regenerated after resumption, so do not * write it out when emptying the buffer externally. */ METHODDEF boolean empty_output_buffer (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != (size_t) OUTPUT_BUF_SIZE) ERREXIT(cinfo, JERR_FILE_WRITE); dest->pub.next_output_byte = dest->buffer; dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; return TRUE; } /* * Terminate destination --- called by jpeg_finish_compress * after all data has been written. Usually needs to flush buffer. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF void term_destination (j_compress_ptr cinfo) { my_dest_ptr dest = (my_dest_ptr) cinfo->dest; size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; /* Write any data remaining in the buffer */ if (datacount > 0) { if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) ERREXIT(cinfo, JERR_FILE_WRITE); } fflush(dest->outfile); /* Make sure we wrote the output file OK */ if (ferror(dest->outfile)) ERREXIT(cinfo, JERR_FILE_WRITE); } /* * Prepare for output to a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing compression. */ GLOBAL void jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) { my_dest_ptr dest; /* The destination object is made permanent so that multiple JPEG images * can be written to the same file without re-executing jpeg_stdio_dest. * This makes it dangerous to use this manager and a different destination * manager serially with the same JPEG object, because their private object * sizes may be different. Caveat programmer. */ if (cinfo->dest == NULL) { /* first time for this JPEG object? */ cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_destination_mgr)); } dest = (my_dest_ptr) cinfo->dest; dest->pub.init_destination = init_destination; dest->pub.empty_output_buffer = empty_output_buffer; dest->pub.term_destination = term_destination; dest->outfile = outfile; } \ No newline at end of file diff --git a/Independent JPEG Group/jdatasrc.c b/Independent JPEG Group/jdatasrc.c new file mode 100644 index 0000000..d601f2b --- /dev/null +++ b/Independent JPEG Group/jdatasrc.c @@ -0,0 +1 @@ +/* * jdatasrc.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains decompression data source routines for the case of * reading JPEG data from a file (or any stdio stream). While these routines * are sufficient for most applications, some will want to use a different * source manager. * IMPORTANT: we assume that fread() will correctly transcribe an array of * JOCTETs from 8-bit-wide elements on external storage. If char is wider * than 8 bits on your machine, you may need to do some tweaking. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jerror.h" /* Expanded data source object for stdio input */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ FILE * infile; /* source stream */ JOCTET * buffer; /* start of buffer */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF void init_source (j_decompress_ptr cinfo) { /* no work necessary here, as jpeg_stdio_src took care of it */ } /* * Fill the input buffer --- called whenever buffer is emptied. * * In typical applications, this should read fresh data into the buffer * (ignoring the current state of next_input_byte & bytes_in_buffer), * reset the pointer & count to the start of the buffer, and return TRUE * indicating that the buffer has been reloaded. It is not necessary to * fill the buffer entirely, only to obtain at least one more byte. * * There is no such thing as an EOF return. If the end of the file has been * reached, the routine has a choice of ERREXIT() or inserting fake data into * the buffer. In most cases, generating a warning message and inserting a * fake EOI marker is the best course of action --- this will allow the * decompressor to output however much of the image is there. * * In applications that need to be able to suspend compression due to input * not being available yet, a FALSE return indicates that no more data can be * obtained right now, but more may be forthcoming later. In this situation, * the decompressor will return to its caller (with an indication of the * number of scanlines it has read, if any). The application should resume * decompression after it has loaded more data into the input buffer. Note * that there are substantial restrictions on the use of suspension --- see * the documentation. * * When suspending, the decompressor will back up to a convenient restart point * (typically the start of the current MCU). next_input_byte & bytes_in_buffer * indicate where the restart point will be if the current call returns FALSE. * Data beyond this point must be rescanned after resumption, so move it to * the front of the buffer rather than discarding it. */ METHODDEF boolean fill_input_buffer (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; size_t nbytes; nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE); if (nbytes <= 0) { WARNMS(cinfo, JWRN_JPEG_EOF); /* Insert a fake EOI marker */ src->buffer[0] = (JOCTET) 0xFF; src->buffer[1] = (JOCTET) JPEG_EOI; nbytes = 2; } src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer = nbytes; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). * * Writers of suspendable-input applications must note that skip_input_data * is not granted the right to give a suspension return. If the skip extends * beyond the data currently in the buffer, the buffer can be marked empty so * that the next read will cause a fill_input_buffer call that can suspend. * Arranging for additional bytes to be discarded before reloading the input * buffer is the application writer's problem. */ METHODDEF void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; /* Just a dumb implementation for now. Could use fseek() except * it doesn't work on pipes. Not clear that being smart is worth * any trouble anyway --- large skips are infrequent. */ if (num_bytes > 0) { while (num_bytes > (long) src->pub.bytes_in_buffer) { num_bytes -= (long) src->pub.bytes_in_buffer; (void) fill_input_buffer(cinfo); } src->pub.next_input_byte += (size_t) num_bytes; src->pub.bytes_in_buffer -= (size_t) num_bytes; } } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. * * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding * application must deal with any cleanup that should happen even * for error exit. */ METHODDEF void term_source (j_decompress_ptr cinfo) { /* no work necessary here */ } /* * Prepare for input from a stdio stream. * The caller must have already opened the stream, and is responsible * for closing it after finishing decompression. */ GLOBAL void jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile) { my_src_ptr src; /* The source object and input buffer are made permanent so that a series * of JPEG images can be read from the same file by calling jpeg_stdio_src * only before the first one. (If we discarded the buffer at the end of * one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(my_source_mgr)); src = (my_src_ptr) cinfo->src; src->buffer = (JOCTET *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET)); } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->infile = infile; src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ } \ No newline at end of file diff --git a/Independent JPEG Group/jdcoefct.c b/Independent JPEG Group/jdcoefct.c new file mode 100644 index 0000000..44da783 --- /dev/null +++ b/Independent JPEG Group/jdcoefct.c @@ -0,0 +1 @@ +/* * jdcoefct.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the coefficient buffer controller for decompression. * This controller is the top level of the JPEG decompressor proper. * The coefficient buffer lies between entropy decoding and inverse-DCT steps. * * For now, this file does not support a full-image coefficient buffer. * One will be necessary to handle noninterleaved or progressive JPEG files. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private buffer controller object */ typedef struct { struct jpeg_d_coef_controller pub; /* public fields */ JDIMENSION MCU_col_num; /* saves next MCU column to process */ JDIMENSION MCU_row_num; /* keep track of MCU row # within image */ /* When not doing block smoothing, it's sufficient to buffer just one MCU * (although this may prove a bit slow in practice). We allocate a * workspace of MAX_BLOCKS_IN_MCU coefficient blocks, and let the entropy * decoder write into that workspace each time. On 80x86, the workspace * is FAR even though it's not really very big; this is to keep the * module interfaces unchanged when a large coefficient buffer is necessary. */ JBLOCKROW MCU_buffer[MAX_BLOCKS_IN_MCU]; } my_coef_controller; typedef my_coef_controller * my_coef_ptr; /* * Initialize for a processing pass. */ METHODDEF void start_pass (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; switch (pass_mode) { case JBUF_PASS_THRU: break; default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } coef->MCU_col_num = 0; coef->MCU_row_num = 0; } /* * Process some data. * Always attempts to emit one fully interleaved MCU row ("iMCU" row). * Returns TRUE if it completed a row, FALSE if not (suspension). * * NB: output_buf contains a plane for each component in image. * For now, we assume this is the same as the components in the scan. */ METHODDEF boolean decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf) { my_coef_ptr coef = (my_coef_ptr) cinfo->coef; JDIMENSION MCU_col_num; /* index of current MCU within row */ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; JDIMENSION last_MCU_row = cinfo->MCU_rows_in_scan - 1; int blkn, ci, xindex, yindex, useful_width; JSAMPARRAY output_ptr; JDIMENSION start_col, output_col; jpeg_component_info *compptr; inverse_DCT_method_ptr inverse_DCT; /* Loop to process as much as one whole MCU row */ for (MCU_col_num = coef->MCU_col_num; MCU_col_num <= last_MCU_col; MCU_col_num++) { /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */ jzero_far((void FAR *) coef->MCU_buffer[0], (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK))); if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) { /* Suspension forced; return with row unfinished */ coef->MCU_col_num = MCU_col_num; /* update my state */ return FALSE; } /* Determine where data should go in output_buf and do the IDCT thing. * We skip dummy blocks at the right and bottom edges (but blkn gets * incremented past them!). Note the inner loop relies on having * allocated the MCU_buffer[] blocks sequentially. */ blkn = 0; /* index of current DCT block within MCU */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Don't bother to IDCT an uninteresting component. */ if (! compptr->component_needed) { blkn += compptr->MCU_blocks; continue; } inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index]; if (MCU_col_num < last_MCU_col) useful_width = compptr->MCU_width; else useful_width = compptr->last_col_width; output_ptr = output_buf[ci]; start_col = MCU_col_num * compptr->MCU_sample_width; for (yindex = 0; yindex < compptr->MCU_height; yindex++) { if (coef->MCU_row_num < last_MCU_row || yindex < compptr->last_row_height) { output_col = start_col; for (xindex = 0; xindex < useful_width; xindex++) { (*inverse_DCT) (cinfo, (JCOEFPTR) coef->MCU_buffer[blkn+xindex], output_ptr, output_col); output_col += compptr->DCT_scaled_size; } } blkn += compptr->MCU_width; output_ptr += compptr->DCT_scaled_size; } } } /* We finished the row successfully */ coef->MCU_col_num = 0; /* prepare for next row */ coef->MCU_row_num++; return TRUE; } /* * Initialize coefficient buffer controller. */ GLOBAL void jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_coef_ptr coef; JBLOCKROW buffer; int i; coef = (my_coef_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_coef_controller)); cinfo->coef = (struct jpeg_d_coef_controller *) coef; coef->pub.start_pass = start_pass; coef->pub.decompress_data = decompress_data; /* Create the coefficient buffer. */ if (need_full_buffer) { ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); } else { buffer = (JBLOCKROW) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); for (i = 0; i < MAX_BLOCKS_IN_MCU; i++) { coef->MCU_buffer[i] = buffer + i; } } } \ No newline at end of file diff --git a/Independent JPEG Group/jdcolor.c b/Independent JPEG Group/jdcolor.c new file mode 100644 index 0000000..babd33e --- /dev/null +++ b/Independent JPEG Group/jdcolor.c @@ -0,0 +1 @@ +/* * jdcolor.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains output colorspace conversion routines. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private subobject */ typedef struct { struct jpeg_color_deconverter pub; /* public fields */ /* Private state for YCC->RGB conversion */ int * Cr_r_tab; /* => table for Cr to R conversion */ int * Cb_b_tab; /* => table for Cb to B conversion */ INT32 * Cr_g_tab; /* => table for Cr to G conversion */ INT32 * Cb_g_tab; /* => table for Cb to G conversion */ } my_color_deconverter; typedef my_color_deconverter * my_cconvert_ptr; /**************** YCbCr -> RGB conversion: most common case **************/ /* * YCbCr is defined per CCIR 601-1, except that Cb and Cr are * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. * The conversion equations to be implemented are therefore * R = Y + 1.40200 * Cr * G = Y - 0.34414 * Cb - 0.71414 * Cr * B = Y + 1.77200 * Cb * where Cb and Cr represent the incoming values less MAXJSAMPLE/2. * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) * * To avoid floating-point arithmetic, we represent the fractional constants * as integers scaled up by 2^16 (about 4 digits precision); we have to divide * the products by 2^16, with appropriate rounding, to get the correct answer. * Notice that Y, being an integral input, does not contribute any fraction * so it need not participate in the rounding. * * For even more speed, we avoid doing any multiplications in the inner loop * by precalculating the constants times Cb and Cr for all possible values. * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); * for 12-bit samples it is still acceptable. It's not very reasonable for * 16-bit samples, but if you want lossless storage you shouldn't be changing * colorspace anyway. * The Cr=>R and Cb=>B values can be rounded to integers in advance; the * values for the G calculation are left scaled up, since we must add them * together before rounding. */ #define SCALEBITS 16 /* speediest right-shift on some machines */ #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) #define FIX(x) ((INT32) ((x) * (1L<RGB colorspace conversion. */ METHODDEF void ycc_rgb_start (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; INT32 i, x2; SHIFT_TEMPS cconvert->Cr_r_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cb_b_tab = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(int)); cconvert->Cr_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); cconvert->Cb_g_tab = (INT32 *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE+1) * SIZEOF(INT32)); for (i = 0; i <= MAXJSAMPLE; i++) { /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ /* The Cb or Cr value we are thinking of is x = i - MAXJSAMPLE/2 */ x2 = 2*i - MAXJSAMPLE; /* twice x */ /* Cr=>R value is nearest int to 1.40200 * x */ cconvert->Cr_r_tab[i] = (int) RIGHT_SHIFT(FIX(1.40200/2) * x2 + ONE_HALF, SCALEBITS); /* Cb=>B value is nearest int to 1.77200 * x */ cconvert->Cb_b_tab[i] = (int) RIGHT_SHIFT(FIX(1.77200/2) * x2 + ONE_HALF, SCALEBITS); /* Cr=>G value is scaled-up -0.71414 * x */ cconvert->Cr_g_tab[i] = (- FIX(0.71414/2)) * x2; /* Cb=>G value is scaled-up -0.34414 * x */ /* We also add in ONE_HALF so that need not do it in inner loop */ cconvert->Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF; } } /* * Convert some rows of samples to the output colorspace. * * Note that we change from noninterleaved, one-plane-per-component format * to interleaved-pixel format. The output buffer is therefore three times * as wide as the input buffer. * A starting row offset is provided only for the input buffer. The caller * can easily adjust the passed output_buf value to accommodate any row * offset required on that side. */ METHODDEF void ycc_rgb_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Note: if the inputs were computed directly from RGB values, * range-limiting would be unnecessary here; but due to possible * noise in the DCT/IDCT phase, we do need to apply range limits. */ #ifdef SLOW outptr[1] = range_limit[y + Crrtab[cr]]; /* red */ outptr[2] = range_limit[y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))]; outptr[3] = range_limit[y + Cbbtab[cb]]; /* blue */ #else *(long *)outptr = (range_limit[y + Crrtab[cr]] << 16) + (range_limit[y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS))] << 8) + range_limit[y + Cbbtab[cb]]; #endif outptr += 4; } } } /**************** Cases other than YCbCr -> RGB **************/ /* * Color conversion for no colorspace change: just copy the data, * converting from separate-planes to interleaved representation. */ METHODDEF void null_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { register JSAMPROW inptr, outptr; register JDIMENSION count; register int num_components = cinfo->output_components; JDIMENSION num_cols = cinfo->output_width; int ci; while (--num_rows >= 0) { for (ci = 0; ci < num_components; ci++) { inptr = input_buf[ci][input_row]; outptr = output_buf[0] + ci; for (count = num_cols; count > 0; count--) { *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ outptr += num_components; } } input_row++; output_buf++; } } /* * Color conversion for grayscale: just copy the data. * This also works for YCbCr -> grayscale conversion, in which * we just copy the Y (luminance) component and ignore chrominance. */ METHODDEF void grayscale_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, num_rows, cinfo->output_width); } /* * Adobe-style YCCK->CMYK conversion. * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same * conversion as above, while passing K (black) unchanged. * We assume ycc_rgb_start has been called. */ METHODDEF void ycck_cmyk_convert (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION input_row, JSAMPARRAY output_buf, int num_rows) { my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; register int y, cb, cr; register JSAMPROW outptr; register JSAMPROW inptr0, inptr1, inptr2, inptr3; register JDIMENSION col; JDIMENSION num_cols = cinfo->output_width; /* copy these pointers into registers if possible */ register JSAMPLE * range_limit = cinfo->sample_range_limit; register int * Crrtab = cconvert->Cr_r_tab; register int * Cbbtab = cconvert->Cb_b_tab; register INT32 * Crgtab = cconvert->Cr_g_tab; register INT32 * Cbgtab = cconvert->Cb_g_tab; SHIFT_TEMPS while (--num_rows >= 0) { inptr0 = input_buf[0][input_row]; inptr1 = input_buf[1][input_row]; inptr2 = input_buf[2][input_row]; inptr3 = input_buf[3][input_row]; input_row++; outptr = *output_buf++; for (col = 0; col < num_cols; col++) { y = GETJSAMPLE(inptr0[col]); cb = GETJSAMPLE(inptr1[col]); cr = GETJSAMPLE(inptr2[col]); /* Note: if the inputs were computed directly from RGB values, * range-limiting would be unnecessary here; but due to possible * noise in the DCT/IDCT phase, we do need to apply range limits. */ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ /* K passes through unchanged */ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ outptr += 4; } } } /* * Empty method for start_pass. */ METHODDEF void null_method (j_decompress_ptr cinfo) { /* no work needed */ } /* * Module initialization routine for output colorspace conversion. */ GLOBAL void jinit_color_deconverter (j_decompress_ptr cinfo) { my_cconvert_ptr cconvert; int ci; cconvert = (my_cconvert_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_color_deconverter)); cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; /* set start_pass to null method until we find out differently */ cconvert->pub.start_pass = null_method; /* Make sure num_components agrees with jpeg_color_space */ switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: if (cinfo->num_components != 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_RGB: case JCS_YCbCr: if (cinfo->num_components != 3) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; case JCS_CMYK: case JCS_YCCK: if (cinfo->num_components != 4) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; default: /* JCS_UNKNOWN can be anything */ if (cinfo->num_components < 1) ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); break; } /* Set out_color_components and conversion method based on requested space. * Also clear the component_needed flags for any unused components, * so that earlier pipeline stages can avoid useless computation. */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; if (cinfo->jpeg_color_space == JCS_GRAYSCALE || cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.color_convert = grayscale_convert; /* For color->grayscale conversion, only the Y (0) component is needed */ for (ci = 1; ci < cinfo->num_components; ci++) cinfo->cur_comp_info[ci]->component_needed = FALSE; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_RGB: cinfo->out_color_components = 3; if (cinfo->jpeg_color_space == JCS_YCbCr) { cconvert->pub.start_pass = ycc_rgb_start; cconvert->pub.color_convert = ycc_rgb_convert; } else if (cinfo->jpeg_color_space == JCS_RGB) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; case JCS_CMYK: cinfo->out_color_components = 4; if (cinfo->jpeg_color_space == JCS_YCCK) { cconvert->pub.start_pass = ycc_rgb_start; cconvert->pub.color_convert = ycck_cmyk_convert; } else if (cinfo->jpeg_color_space == JCS_CMYK) { cconvert->pub.color_convert = null_convert; } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; default: /* Permit null conversion to same output space */ if (cinfo->out_color_space == cinfo->jpeg_color_space) { cinfo->out_color_components = cinfo->num_components; cconvert->pub.color_convert = null_convert; } else /* unsupported non-null conversion */ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break; } if (cinfo->quantize_colors) cinfo->output_components = 1; /* single colormapped output component */ else cinfo->output_components = cinfo->out_color_components; } \ No newline at end of file diff --git a/Independent JPEG Group/jdct.h b/Independent JPEG Group/jdct.h new file mode 100644 index 0000000..fc8821b --- /dev/null +++ b/Independent JPEG Group/jdct.h @@ -0,0 +1 @@ +/* * jdct.h * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file contains common declarations for the forward and * inverse DCT modules. These declarations are private to the DCT managers * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms. * The individual DCT algorithms are kept in separate files to ease * machine-dependent tuning (e.g., assembly coding). */ /* * A forward DCT routine is given a pointer to a work area of type int[]; * the DCT is to be performed in-place in that buffer. (May want to change * this??) * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE). * For now, quantization of the output coefficients is done by jcdctmgr.c. */ typedef JMETHOD(void, forward_dct_method_ptr, (int * data)); /* * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer * to an output sample array. The output data is to be placed into the * sample array starting at a specified column. (Any row offset needed will * be applied to the array pointer before it is passed to the IDCT code.) * Note that the number of samples emitted by the IDCT routine is * DCT_scaled_size * DCT_scaled_size. */ /* typedef inverse_DCT_method_ptr is declared in jpegint.h */ /* * Each IDCT routine is responsible for range-limiting its results and * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could * be quite far out of range if the input data is corrupt, so a bulletproof * range-limiting step is required. We use a mask-and-table-lookup method * to do the combined operations quickly. See the comments with * prepare_range_limit_table (in jdmaster.c) for more info. */ #define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE) #define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */ /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_fdct_llm jFDllm #define jpeg_idct_llm jRDllm #define jpeg_idct_4x4 jRD4x4 #define jpeg_idct_2x2 jRD2x2 #define jpeg_idct_1x1 jRD1x1 #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Extern declarations for the forward and inverse DCT routines. */ EXTERN void jpeg_fdct_llm JPP((int * data)); EXTERN void jpeg_idct_llm JPP((j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN void jpeg_idct_4x4 JPP((j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN void jpeg_idct_2x2 JPP((j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); EXTERN void jpeg_idct_1x1 JPP((j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col)); \ No newline at end of file diff --git a/Independent JPEG Group/jddctmgr.c b/Independent JPEG Group/jddctmgr.c new file mode 100644 index 0000000..a9fe140 --- /dev/null +++ b/Independent JPEG Group/jddctmgr.c @@ -0,0 +1 @@ +/* * jddctmgr.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the inverse-DCT management logic. * This code selects a particular IDCT implementation to be used, * and it performs related housekeeping chores. No code in this file * is executed per IDCT step, only during setup. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* Private subobject for this module */ typedef struct { struct jpeg_inverse_dct pub; /* public fields */ /* no private fields for now */ } my_idct_controller; typedef my_idct_controller * my_idct_ptr; /* * Initialize for a processing pass. * Verify that all referenced Q-tables are present, and set up * the multiplier tables for each one. */ METHODDEF void start_pass (j_decompress_ptr cinfo) { int ci, qtblno, i; JDQUANT_TBL * qtbl; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { qtblno = cinfo->cur_comp_info[ci]->quant_tbl_no; /* Make sure specified quantization table is present */ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || cinfo->quant_tbl_ptrs[qtblno] == NULL) ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); /* Compute multipliers for this quant table */ /* We may do this more than once for same table, but it's not a big deal */ qtbl = (JDQUANT_TBL *) cinfo->quant_tbl_ptrs[qtblno]; for (i = 0; i < DCTSIZE2; i++) { /* For now, multipliers are same as raw quantization coefficients */ qtbl->multipliers[i] = (MULTIPLIER) qtbl->pub.quantval[i]; } } } /* * Initialize IDCT manager. */ GLOBAL void jinit_inverse_dct (j_decompress_ptr cinfo) { my_idct_ptr idct; int ci; jpeg_component_info * compptr; idct = (my_idct_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_idct_controller)); cinfo->idct = (struct jpeg_inverse_dct *) idct; idct->pub.start_pass = start_pass; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { switch (compptr->DCT_scaled_size) { #ifdef IDCT_SCALING_SUPPORTED case 1: idct->pub.inverse_DCT[ci] = jpeg_idct_1x1; break; case 2: idct->pub.inverse_DCT[ci] = jpeg_idct_2x2; break; case 4: idct->pub.inverse_DCT[ci] = jpeg_idct_4x4; break; #endif case DCTSIZE: idct->pub.inverse_DCT[ci] = jpeg_idct_llm; break; default: ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->DCT_scaled_size); break; } } } \ No newline at end of file diff --git a/Independent JPEG Group/jdhuff.c b/Independent JPEG Group/jdhuff.c new file mode 100644 index 0000000..99ca287 --- /dev/null +++ b/Independent JPEG Group/jdhuff.c @@ -0,0 +1 @@ +/* * jdhuff.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains Huffman entropy decoding routines. * * Much of the complexity here has to do with supporting input suspension. * If the data source module demands suspension, we want to be able to back * up to the start of the current MCU. To do this, we copy state variables * into local working storage, and update them back to the permanent JPEG * objects only upon successful completion of an MCU. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Expanded entropy decoder object for Huffman decoding. * * The savable_state subrecord contains fields that change within an MCU, * but must not be updated permanently until we complete the MCU. */ typedef struct { INT32 get_buffer; /* current bit-extraction buffer */ int bits_left; /* # of unused bits in it */ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ } savable_state; typedef struct { struct jpeg_entropy_decoder pub; /* public fields */ savable_state saved; /* Bit buffer & DC state at start of MCU */ /* These fields are NOT loaded into local working state. */ unsigned int restarts_to_go; /* MCUs left in this restart interval */ boolean printed_eod; /* flag to suppress extra end-of-data msgs */ } huff_entropy_decoder; typedef huff_entropy_decoder * huff_entropy_ptr; /* Working state while scanning an MCU. * This struct contains all the fields that are needed by subroutines. */ typedef struct { int unread_marker; /* nonzero if we have hit a marker */ const JOCTET * next_input_byte; /* => next byte to read from source */ size_t bytes_in_buffer; /* # of bytes remaining in source buffer */ savable_state cur; /* Current bit buffer & DC state */ j_decompress_ptr cinfo; /* fill_bit_buffer needs access to this */ } working_state; /* Forward declarations */ LOCAL void fix_huff_tbl JPP((JDHUFF_TBL * htbl)); /* * Initialize for a Huffman-compressed scan. */ METHODDEF void start_pass (j_decompress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci, dctbl, actbl; jpeg_component_info * compptr; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; dctbl = compptr->dc_tbl_no; actbl = compptr->ac_tbl_no; /* Make sure requested tables are present */ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS || cinfo->dc_huff_tbl_ptrs[dctbl] == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); if (actbl < 0 || actbl >= NUM_HUFF_TBLS || cinfo->ac_huff_tbl_ptrs[actbl] == NULL) ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); /* Compute derived values for Huffman tables */ /* We may do this more than once for same table, but it's not a big deal */ fix_huff_tbl((JDHUFF_TBL *) cinfo->dc_huff_tbl_ptrs[dctbl]); fix_huff_tbl((JDHUFF_TBL *) cinfo->ac_huff_tbl_ptrs[actbl]); /* Initialize DC predictions to 0 */ entropy->saved.last_dc_val[ci] = 0; } /* Initialize private state variables */ entropy->saved.bits_left = 0; entropy->printed_eod = FALSE; /* Initialize restart counter */ entropy->restarts_to_go = cinfo->restart_interval; } LOCAL void fix_huff_tbl (JDHUFF_TBL * htbl) /* Compute the derived values for a Huffman table */ { int p, i, l, si; int lookbits, ctr; char huffsize[257]; unsigned int huffcode[257]; unsigned int code; /* Figure C.1: make table of Huffman code length for each symbol */ /* Note that this is in code-length order. */ p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= (int) htbl->pub.bits[l]; i++) huffsize[p++] = (char) l; } huffsize[p] = 0; /* Figure C.2: generate the codes themselves */ /* Note that this is in code-length order. */ code = 0; si = huffsize[0]; p = 0; while (huffsize[p]) { while (((int) huffsize[p]) == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } /* Figure F.15: generate decoding tables for bit-sequential decoding */ p = 0; for (l = 1; l <= 16; l++) { if (htbl->pub.bits[l]) { htbl->valptr[l] = p; /* huffval[] index of 1st symbol of code length l */ htbl->mincode[l] = huffcode[p]; /* minimum code of length l */ p += htbl->pub.bits[l]; htbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */ } else { htbl->maxcode[l] = -1; /* -1 if no codes of this length */ } } htbl->maxcode[17] = 0xFFFFFL; /* ensures huff_DECODE terminates */ /* Compute lookahead tables to speed up decoding. * First we set all the table entries to 0, indicating "too long"; * then we iterate through the Huffman codes that are short enough and * fill in all the entries that correspond to bit sequences starting * with that code. */ MEMZERO(htbl->look_nbits, SIZEOF(htbl->look_nbits)); p = 0; for (l = 1; l <= HUFF_LOOKAHEAD; l++) { for (i = 1; i <= (int) htbl->pub.bits[l]; i++, p++) { /* l = current code's length, p = its index in huffcode[] & huffval[]. */ /* Generate left-justified code followed by all possible bit sequences */ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l); for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) { htbl->look_nbits[lookbits] = l; htbl->look_sym[lookbits] = htbl->pub.huffval[p]; lookbits++; } } } } /* * Code for extracting the next N bits from the input stream. * (N never exceeds 15 for JPEG data.) * This needs to go as fast as possible! * * We read source bytes into get_buffer and dole out bits as needed. * If get_buffer already contains enough bits, they are fetched in-line * by the macros check_bit_buffer and get_bits. When there aren't enough * bits, fill_bit_buffer is called; it will attempt to fill get_buffer to * the "high water mark" (not just to the number of bits needed; this reduces * the function-call overhead cost of entering fill_bit_buffer). * Note that fill_bit_buffer may return FALSE to indicate suspension. * On TRUE return, fill_bit_buffer guarantees that get_buffer contains * at least the requested number of bits --- dummy zeroes are inserted if * necessary. * * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width * of get_buffer to be used. (On machines with wider words, an even larger * buffer could be used.) However, on some machines 32-bit shifts are * quite slow and take time proportional to the number of places shifted. * (This is true with most PC compilers, for instance.) In this case it may * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the * average shift distance at the cost of more calls to fill_bit_buffer. */ #ifdef SLOW_SHIFT_32 #define MIN_GET_BITS 15 /* minimum allowable value */ #else #define MIN_GET_BITS 25 /* max value for 32-bit get_buffer */ #endif LOCAL boolean fill_bit_buffer (working_state * state, int nbits) /* Load up the bit buffer to a depth of at least nbits */ { /* Copy heavily used state fields into locals (hopefully registers) */ register const JOCTET * next_input_byte = state->next_input_byte; register size_t bytes_in_buffer = state->bytes_in_buffer; register INT32 get_buffer = state->cur.get_buffer; register int bits_left = state->cur.bits_left; register int c; /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */ /* (It is assumed that no request will be for more than that many bits.) */ while (bits_left < MIN_GET_BITS) { /* Attempt to read a byte */ if (state->unread_marker != 0) goto no_more_data; /* can't advance past a marker */ if (bytes_in_buffer == 0) { if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo)) return FALSE; next_input_byte = state->cinfo->src->next_input_byte; bytes_in_buffer = state->cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); /* If it's 0xFF, check and discard stuffed zero byte */ if (c == 0xFF) { do { if (bytes_in_buffer == 0) { if (! (*state->cinfo->src->fill_input_buffer) (state->cinfo)) return FALSE; next_input_byte = state->cinfo->src->next_input_byte; bytes_in_buffer = state->cinfo->src->bytes_in_buffer; } bytes_in_buffer--; c = GETJOCTET(*next_input_byte++); } while (c == 0xFF); if (c == 0) { /* Found FF/00, which represents an FF data byte */ c = 0xFF; } else { /* Oops, it's actually a marker indicating end of compressed data. */ /* Better put it back for use later */ state->unread_marker = c; no_more_data: /* There should be enough bits still left in the data segment; */ /* if so, just break out of the outer while loop. */ if (bits_left >= nbits) break; /* Uh-oh. Report corrupted data to user and stuff zeroes into * the data stream, so that we can produce some kind of image. * Note that this will be repeated for each byte demanded for the * rest of the segment; this is slow but not unreasonably so. * The main thing is to avoid getting a zillion warnings, hence * we use a flag to ensure that only one warning appears. */ if (! ((huff_entropy_ptr) state->cinfo->entropy)->printed_eod) { WARNMS(state->cinfo, JWRN_HIT_MARKER); ((huff_entropy_ptr) state->cinfo->entropy)->printed_eod = TRUE; } c = 0; /* insert a zero byte into bit buffer */ } } /* OK, load c into get_buffer */ get_buffer = (get_buffer << 8) | c; bits_left += 8; } /* Unload the local registers */ state->next_input_byte = next_input_byte; state->bytes_in_buffer = bytes_in_buffer; state->cur.get_buffer = get_buffer; state->cur.bits_left = bits_left; return TRUE; } /* * These macros provide the in-line portion of bit fetching. * Use check_bit_buffer to ensure there are N bits in get_buffer * before using get_bits, peek_bits, or drop_bits. * check_bit_buffer(state,n,action); * Ensure there are N bits in get_buffer; if suspend, take action. * val = get_bits(state,n); * Fetch next N bits. * val = peek_bits(state,n); * Fetch next N bits without removing them from the buffer. * drop_bits(state,n); * Discard next N bits. * The value N should be a simple variable, not an expression, because it * is evaluated multiple times. */ #define check_bit_buffer(state,nbits,action) \ { if ((state).cur.bits_left < (nbits)) \ if (! fill_bit_buffer(&(state), nbits)) \ { action; } } #define get_bits(state,nbits) \ (((int) ((state).cur.get_buffer >> ((state).cur.bits_left -= (nbits)))) & ((1<<(nbits))-1)) #define peek_bits(state,nbits) \ (((int) ((state).cur.get_buffer >> ((state).cur.bits_left - (nbits)))) & ((1<<(nbits))-1)) #define drop_bits(state,nbits) \ ((state).cur.bits_left -= (nbits)) /* * Code for extracting next Huffman-coded symbol from input bit stream. * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits * without looping. Usually, more than 95% of the Huffman codes will be 8 * or fewer bits long. The few overlength codes are handled with a loop. * The primary case is made a macro for speed reasons; the secondary * routine slow_DECODE is rarely entered and need not be inline code. * * Notes about the huff_DECODE macro: * 1. Near the end of the data segment, we may fail to get enough bits * for a lookahead. In that case, we do it the hard way. * 2. If the lookahead table contains no entry, the next code must be * more than HUFF_LOOKAHEAD bits long. * 3. slow_DECODE returns -1 if forced to suspend. */ #define huff_DECODE(result,state,htbl,donelabel) \ { if (state.cur.bits_left < HUFF_LOOKAHEAD) { \ if (! fill_bit_buffer(&state, 0)) return FALSE; \ if (state.cur.bits_left < HUFF_LOOKAHEAD) { \ if ((result = slow_DECODE(&state, htbl, 1)) < 0) return FALSE; \ goto donelabel; \ } \ } \ { register int nb, look; \ look = peek_bits(state, HUFF_LOOKAHEAD); \ if ((nb = htbl->look_nbits[look]) != 0) { \ drop_bits(state, nb); \ result = htbl->look_sym[look]; \ } else { \ if ((result = slow_DECODE(&state, htbl, HUFF_LOOKAHEAD+1)) < 0) \ return FALSE; \ } \ } \ donelabel:; \ } LOCAL int slow_DECODE (working_state * state, JDHUFF_TBL * htbl, int min_bits) { register int l = min_bits; register INT32 code; /* huff_DECODE has determined that the code is at least min_bits */ /* bits long, so fetch that many bits in one swoop. */ check_bit_buffer(*state, l, return -1); code = get_bits(*state, l); /* Collect the rest of the Huffman code one bit at a time. */ /* This is per Figure F.16 in the JPEG spec. */ while (code > htbl->maxcode[l]) { code <<= 1; check_bit_buffer(*state, 1, return -1); code |= get_bits(*state, 1); l++; } /* With garbage input we may reach the sentinel value l = 17. */ if (l > 16) { WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE); return 0; /* fake a zero as the safest result */ } return htbl->pub.huffval[ htbl->valptr[l] + ((int) (code - htbl->mincode[l])) ]; } /* Figure F.12: extend sign bit. * On some machines, a shift and add will be faster than a table lookup. */ #ifdef AVOID_TABLES #define huff_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x)) #else #define huff_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x)) static const int extend_test[16] = /* entry n is 2**(n-1) */ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; #endif /* AVOID_TABLES */ /* * Check for a restart marker & resynchronize decoder. * Returns FALSE if must suspend. */ LOCAL boolean process_restart (j_decompress_ptr cinfo) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; int ci; /* Throw away any unused bits remaining in bit buffer; */ /* include any full bytes in next_marker's count of discarded bytes */ cinfo->marker->discarded_bytes += entropy->saved.bits_left / 8; entropy->saved.bits_left = 0; /* Advance past the RSTn marker */ if (! (*cinfo->marker->read_restart_marker) (cinfo)) return FALSE; /* Re-initialize DC predictions to 0 */ for (ci = 0; ci < cinfo->comps_in_scan; ci++) entropy->saved.last_dc_val[ci] = 0; /* Reset restart counter */ entropy->restarts_to_go = cinfo->restart_interval; entropy->printed_eod = FALSE; /* next segment can get another warning */ return TRUE; } /* ZAG[i] is the natural-order position of the i'th element of zigzag order. * If the incoming data is corrupted, decode_mcu could attempt to * reference values beyond the end of the array. To avoid a wild store, * we put some extra zeroes after the real entries. */ static const int ZAG[DCTSIZE2+16] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, 0, 0, 0, 0, 0, 0, 0, 0, /* extra entries in case k>63 below */ 0, 0, 0, 0, 0, 0, 0, 0 }; /* * Decode and return one MCU's worth of Huffman-compressed coefficients. * This routine also handles quantization descaling and zigzag reordering * of coefficient values. * * The i'th block of the MCU is stored into the block pointed to by * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER. * (Wholesale zeroing is usually a little faster than retail...) * * Returns FALSE if data source requested suspension. In that case no * changes have been made to permanent state. (Exception: some output * coefficients may already have been assigned. This is harmless for * this module, but would not work for decoding progressive JPEG.) */ METHODDEF boolean decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data) { huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; register int s, k, r; int blkn, ci; register JBLOCKROW block; register MULTIPLIER * multiplier_ptr; working_state state; JDQUANT_TBL * qtbl; JDHUFF_TBL * dctbl; JDHUFF_TBL * actbl; jpeg_component_info * compptr; /* Process restart marker if needed; may have to suspend */ if (cinfo->restart_interval) { if (entropy->restarts_to_go == 0) if (! process_restart(cinfo)) return FALSE; } /* Load up working state */ state.unread_marker = cinfo->unread_marker; state.next_input_byte = cinfo->src->next_input_byte; state.bytes_in_buffer = cinfo->src->bytes_in_buffer; state.cur = entropy->saved; state.cinfo = cinfo; /* Outer loop handles each block in the MCU */ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { block = MCU_data[blkn]; ci = cinfo->MCU_membership[blkn]; compptr = cinfo->cur_comp_info[ci]; dctbl = (JDHUFF_TBL *) cinfo->dc_huff_tbl_ptrs[compptr->dc_tbl_no]; actbl = (JDHUFF_TBL *) cinfo->ac_huff_tbl_ptrs[compptr->ac_tbl_no]; qtbl = (JDQUANT_TBL *) cinfo->quant_tbl_ptrs[compptr->quant_tbl_no]; multiplier_ptr = qtbl->multipliers; /* Decode a single block's worth of coefficients */ /* Section F.2.2.1: decode the DC coefficient difference */ huff_DECODE(s, state, dctbl, label1); if (s) { check_bit_buffer(state, s, return FALSE); r = get_bits(state, s); s = huff_EXTEND(r, s); } /* Shortcut if component's values are not interesting */ if (! compptr->component_needed) goto skip_ACs; /* Convert DC difference to actual value, update last_dc_val */ s += state.cur.last_dc_val[ci]; state.cur.last_dc_val[ci] = s; /* Descale and output the DC coefficient (assumes ZAG[0] = 0) */ (*block)[0] = (JCOEF) (((MULTIPLIER) s) * multiplier_ptr[0]); /* Do we need to decode the AC coefficients for this component? */ if (compptr->DCT_scaled_size > 1) { /* Section F.2.2.2: decode the AC coefficients */ /* Since zeroes are skipped, output area must be cleared beforehand */ for (k = 1; k < DCTSIZE2; k++) { huff_DECODE(s, state, actbl, label2); r = s >> 4; s &= 15; if (s) { k += r; check_bit_buffer(state, s, return FALSE); r = get_bits(state, s); s = huff_EXTEND(r, s); /* Descale coefficient and output in natural (dezigzagged) order */ (*block)[ZAG[k]] = (JCOEF) (((MULTIPLIER) s) * multiplier_ptr[k]); } else { if (r != 15) break; k += 15; } } } else { skip_ACs: /* Section F.2.2.2: decode the AC coefficients */ /* In this path we just discard the values */ for (k = 1; k < DCTSIZE2; k++) { huff_DECODE(s, state, actbl, label3); r = s >> 4; s &= 15; if (s) { k += r; check_bit_buffer(state, s, return FALSE); drop_bits(state, s); } else { if (r != 15) break; k += 15; } } } } /* Completed MCU, so update state */ cinfo->unread_marker = state.unread_marker; cinfo->src->next_input_byte = state.next_input_byte; cinfo->src->bytes_in_buffer = state.bytes_in_buffer; entropy->saved = state.cur; /* Account for restart interval (no-op if not using restarts) */ entropy->restarts_to_go--; return TRUE; } /* * Module initialization routine for Huffman entropy decoding. */ GLOBAL void jinit_huff_decoder (j_decompress_ptr cinfo) { cinfo->entropy = (struct jpeg_entropy_decoder *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(huff_entropy_decoder)); cinfo->entropy->start_pass = start_pass; cinfo->entropy->decode_mcu = decode_mcu; } \ No newline at end of file diff --git a/Independent JPEG Group/jdmainct.c b/Independent JPEG Group/jdmainct.c new file mode 100644 index 0000000..87822cf --- /dev/null +++ b/Independent JPEG Group/jdmainct.c @@ -0,0 +1 @@ +/* * jdmainct.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the main buffer controller for decompression. * The main buffer lies between the JPEG decompressor proper and the * post-processor; it holds downsampled data in the JPEG colorspace. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * In the current system design, the main buffer need never be a full-image * buffer; any full-height buffers will be found inside the coefficient or * postprocessing controllers. Nonetheless, the main controller is not * trivial. Its responsibility is to provide context rows for upsampling/ * rescaling, and doing this in an efficient fashion is a bit tricky. * * Postprocessor input data is counted in "row groups". A row group * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) * sample rows of each component. (We require DCT_scaled_size values to be * chosen such that these numbers are integers. In practice DCT_scaled_size * values will likely be powers of two, so we actually have the stronger * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.) * Upsampling will typically produce max_v_samp_factor pixel rows from each * row group (times any additional scale factor that the upsampler is * applying). * * The coefficient controller will deliver data to us one iMCU row at a time; * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or * exactly min_DCT_scaled_size row groups. (This amount of data corresponds * to one row of MCUs when the image is fully interleaved.) Note that the * number of sample rows varies across components, but the number of row * groups does not. Some garbage sample rows may be included in the last iMCU * row at the bottom of the image. * * Depending on the vertical scaling algorithm used, the upsampler may need * access to the sample row(s) above and below its current input row group. * The upsampler is required to set need_context_rows TRUE at global selection * time if so. When need_context_rows is FALSE, this controller can simply * obtain one iMCU row at a time from the coefficient controller and dole it * out as row groups to the postprocessor. * * When need_context_rows is TRUE, this controller guarantees that the buffer * passed to postprocessing contains at least one row group's worth of samples * above and below the row group(s) being processed. Note that the context * rows "above" the first passed row group appear at negative row offsets in * the passed buffer. At the top and bottom of the image, the required * context rows are manufactured by duplicating the first or last real sample * row; this avoids having special cases in the upsampling inner loops. * * The amount of context is fixed at one row group just because that's a * convenient number for this controller to work with. The existing * upsamplers really only need one sample row of context. An upsampler * supporting arbitrary output rescaling might wish for more than one row * group of context when shrinking the image; tough, we don't handle that. * (This is justified by the assumption that downsizing will be handled mostly * by adjusting the DCT_scaled_size values, so that the actual scale factor at * the upsample step needn't be much less than one.) * * To provide the desired context, we have to retain the last two row groups * of one iMCU row while reading in the next iMCU row. (The last row group * can't be processed until we have another row group for its below-context, * and so we have to save the next-to-last group too for its above-context.) * We could do this most simply by copying data around in our buffer, but * that'd be very slow. We can avoid copying any data by creating a rather * strange pointer structure. Here's how it works. We allocate a workspace * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number * of row groups per iMCU row). We create two sets of redundant pointers to * the workspace. Labeling the physical row groups 0 to M+1, the synthesized * pointer lists look like this: * M+1 M-1 * master pointer --> 0 master pointer --> 0 * 1 1 * ... ... * M-3 M-3 * M-2 M * M-1 M+1 * M M-2 * M+1 M-1 * 0 0 * We read alternate iMCU rows using each master pointer; thus the last two * row groups of the previous iMCU row remain un-overwritten in the workspace. * The pointer lists are set up so that the required context rows appear to * be adjacent to the proper places when we pass the pointer lists to the * upsampler. * * The above pictures describe the normal state of the pointer lists. * At top and bottom of the image, we diddle the pointer lists to duplicate * the first or last sample row as necessary (this is cheaper than copying * sample rows around). * * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that * situation each iMCU row provides only one row group so the buffering logic * must be different (eg, we must read two iMCU rows before we can emit the * first row group). For now, we simply do not support providing context * rows when min_DCT_scaled_size is 1. That combination seems unlikely to * be worth providing --- if someone wants a 1/8th-size preview, they probably * want it quick and dirty, so a context-free upsampler is sufficient. */ /* Private buffer controller object */ typedef struct { struct jpeg_d_main_controller pub; /* public fields */ /* Pointer to allocated workspace (M or M+2 row groups). */ JSAMPARRAY buffer[MAX_COMPONENTS]; boolean buffer_full; /* Have we gotten an iMCU row from decoder? */ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */ /* Remaining fields are only used in the context case. */ /* These are the master pointers to the funny-order pointer lists. */ JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */ int whichptr; /* indicates which pointer set is now in use */ int context_state; /* process_data state machine status */ JDIMENSION rowgroups_avail; /* row groups available to postprocessor */ JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */ } my_main_controller; typedef my_main_controller * my_main_ptr; /* context_state values: */ #define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */ #define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */ #define CTX_POSTPONED_ROW 2 /* feeding postponed row group */ /* Forward declarations */ METHODDEF void process_data_simple_main JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF void process_data_context_main JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF void process_data_crank_post JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif LOCAL void make_funny_pointers (j_decompress_ptr cinfo) /* Create the funny pointer lists discussed in the comments above. * The actual workspace is already allocated (in main->buffer), * we just have to make the curiously ordered lists. */ { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_scaled_size; jpeg_component_info *compptr; JSAMPARRAY buf, xbuf0, xbuf1; /* Get top-level space for component array pointers. * We alloc both arrays with one call to save a few cycles. */ main->xbuffer[0] = (JSAMPIMAGE) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * 2 * SIZEOF(JSAMPARRAY)); main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; /* height of a row group of component */ /* Get space for pointer lists --- M+4 row groups in each list. * We alloc both pointer lists with one call to save a few cycles. */ xbuf0 = (JSAMPARRAY) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW)); xbuf0 += rgroup; /* want one row group at negative offsets */ main->xbuffer[0][ci] = xbuf0; xbuf1 = xbuf0 + (rgroup * (M + 4)); main->xbuffer[1][ci] = xbuf1; /* First copy the workspace pointers as-is */ buf = main->buffer[ci]; for (i = 0; i < rgroup * (M + 2); i++) { xbuf0[i] = xbuf1[i] = buf[i]; } /* In the second list, put the last four row groups in swapped order */ for (i = 0; i < rgroup * 2; i++) { xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i]; xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i]; } /* The wraparound pointers at top and bottom will be filled later * (see set_wraparound_pointers, below). Initially we want the "above" * pointers to duplicate the first actual data line. This only needs * to happen in xbuffer[0]. */ for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[0]; } } } LOCAL void set_wraparound_pointers (j_decompress_ptr cinfo) /* Set up the "wraparound" pointers at top and bottom of the pointer lists. * This changes the pointer list state from top-of-image to the normal state. */ { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup; int M = cinfo->min_DCT_scaled_size; jpeg_component_info *compptr; JSAMPARRAY xbuf0, xbuf1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; /* height of a row group of component */ xbuf0 = main->xbuffer[0][ci]; xbuf1 = main->xbuffer[1][ci]; for (i = 0; i < rgroup; i++) { xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i]; xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i]; xbuf0[rgroup*(M+2) + i] = xbuf0[i]; xbuf1[rgroup*(M+2) + i] = xbuf1[i]; } } } LOCAL void set_bottom_pointers (j_decompress_ptr cinfo) /* Change the pointer lists to duplicate the last sample row at the bottom * of the image. whichptr indicates which xbuffer holds the final iMCU row. * Also sets rowgroups_avail to indicate number of nondummy row groups in row. */ { my_main_ptr main = (my_main_ptr) cinfo->main; int ci, i, rgroup, iMCUheight, rows_left; jpeg_component_info *compptr; JSAMPARRAY xbuf; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Count sample rows in one iMCU row and in one row group */ iMCUheight = compptr->v_samp_factor * compptr->DCT_scaled_size; rgroup = iMCUheight / cinfo->min_DCT_scaled_size; /* Count nondummy sample rows remaining for this component */ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight); if (rows_left == 0) rows_left = iMCUheight; /* Count nondummy row groups. Should get same answer for each component, * so we need only do it once. */ if (ci == 0) { main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1); } /* Duplicate the last real sample row rgroup*2 times; this pads out the * last partial rowgroup and ensures at least one full rowgroup of context. */ xbuf = main->xbuffer[main->whichptr][ci]; for (i = 0; i < rgroup * 2; i++) { xbuf[rows_left + i] = xbuf[rows_left-1]; } } } /* * Initialize for a processing pass. */ METHODDEF void start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { my_main_ptr main = (my_main_ptr) cinfo->main; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->upsample->need_context_rows) { main->pub.process_data = process_data_context_main; make_funny_pointers(cinfo); /* Create the xbuffer[] lists */ main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */ main->context_state = CTX_PREPARE_FOR_IMCU; main->iMCU_row_ctr = 0; } else { /* Simple case with no context needed */ main->pub.process_data = process_data_simple_main; } main->buffer_full = FALSE; /* Mark buffer empty */ main->rowgroup_ctr = 0; break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_CRANK_DEST: /* For last pass of 2-pass quantization, just crank the postprocessor */ main->pub.process_data = process_data_crank_post; break; #endif default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } } /* * Process some data. * This handles the simple case where no context is required. */ METHODDEF void process_data_simple_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; JDIMENSION rowgroups_avail; /* Read input data if we haven't filled the main buffer yet */ if (! main->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer)) return; /* suspension forced, can do nothing more */ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ } /* There are always min_DCT_scaled_size row groups in an iMCU row. */ rowgroups_avail = (JDIMENSION) cinfo->min_DCT_scaled_size; /* Note: at the bottom of the image, we may pass extra garbage row groups * to the postprocessor. The postprocessor has to check for bottom * of image anyway (at row resolution), so no point in us doing it too. */ /* Feed the postprocessor */ (*cinfo->post->post_process_data) (cinfo, main->buffer, &main->rowgroup_ctr, rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); /* Has postprocessor consumed all the data yet? If so, mark buffer empty */ if (main->rowgroup_ctr >= rowgroups_avail) { main->buffer_full = FALSE; main->rowgroup_ctr = 0; } } /* * Process some data. * This handles the case where context rows must be provided. */ METHODDEF void process_data_context_main (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_main_ptr main = (my_main_ptr) cinfo->main; /* Read input data if we haven't filled the main buffer yet */ if (! main->buffer_full) { if (! (*cinfo->coef->decompress_data) (cinfo, main->xbuffer[main->whichptr])) return; /* suspension forced, can do nothing more */ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */ main->iMCU_row_ctr++; /* count rows received */ } /* Postprocessor typically will not swallow all the input data it is handed * in one call (due to filling the output buffer first). Must be prepared * to exit and restart. This switch lets us keep track of how far we got. * Note that each case falls through to the next on successful completion. */ switch (main->context_state) { case CTX_POSTPONED_ROW: /* Call postprocessor using previously set pointers for postponed row */ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], &main->rowgroup_ctr, main->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); if (main->rowgroup_ctr < main->rowgroups_avail) return; /* Need to suspend */ main->context_state = CTX_PREPARE_FOR_IMCU; /*FALLTHROUGH*/ case CTX_PREPARE_FOR_IMCU: /* Prepare to process first M-1 row groups of this iMCU row */ main->rowgroup_ctr = 0; main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size - 1); /* Check for bottom of image: if so, tweak pointers to "duplicate" * the last sample row, and adjust rowgroups_avail to ignore padding rows. */ if (main->iMCU_row_ctr == cinfo->total_iMCU_rows) set_bottom_pointers(cinfo); main->context_state = CTX_PROCESS_IMCU; /*FALLTHROUGH*/ case CTX_PROCESS_IMCU: /* Call postprocessor using previously set pointers */ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr], &main->rowgroup_ctr, main->rowgroups_avail, output_buf, out_row_ctr, out_rows_avail); if (main->rowgroup_ctr < main->rowgroups_avail) return; /* Need to suspend */ /* After the first iMCU, change wraparound pointers to normal state */ if (main->iMCU_row_ctr == 1) set_wraparound_pointers(cinfo); /* Prepare to load new iMCU row using other xbuffer list */ main->whichptr ^= 1; /* 0=>1 or 1=>0 */ main->buffer_full = FALSE; /* Still need to process last row group of this iMCU row, */ /* which is saved at index M+1 of the other xbuffer */ main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_scaled_size + 1); main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_scaled_size + 2); main->context_state = CTX_POSTPONED_ROW; } } /* * Process some data. * Final pass of two-pass quantization: just call the postprocessor. * Source data will be the postprocessor controller's internal buffer. */ #ifdef QUANT_2PASS_SUPPORTED METHODDEF void process_data_crank_post (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { (*cinfo->post->post_process_data) (cinfo, NULL, NULL, (JDIMENSION) 0, output_buf, out_row_ctr, out_rows_avail); } #endif /* QUANT_2PASS_SUPPORTED */ /* * Initialize main buffer controller. */ GLOBAL void jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_main_ptr main; int ci, rgroup, ngroups; jpeg_component_info *compptr; main = (my_main_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_main_controller)); cinfo->main = (struct jpeg_d_main_controller *) main; main->pub.start_pass = start_pass_main; if (need_full_buffer) /* shouldn't happen */ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); /* Allocate the workspace. * ngroups is the number of row groups we need. */ if (cinfo->upsample->need_context_rows) { if (cinfo->min_DCT_scaled_size < 2) /* unsupported, see comments above */ ERREXIT(cinfo, JERR_NOTIMPL); ngroups = cinfo->min_DCT_scaled_size + 2; } else { ngroups = cinfo->min_DCT_scaled_size; } for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { rgroup = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; /* height of a row group of component */ main->buffer[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, compptr->width_in_blocks * compptr->DCT_scaled_size, (JDIMENSION) (rgroup * ngroups)); } } \ No newline at end of file diff --git a/Independent JPEG Group/jdmarker.c b/Independent JPEG Group/jdmarker.c new file mode 100644 index 0000000..3da2ab2 --- /dev/null +++ b/Independent JPEG Group/jdmarker.c @@ -0,0 +1 @@ +/* * jdmarker.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to decode JPEG datastream markers. * Most of the complexity arises from our desire to support input * suspension: if not all of the data for a marker is available, * we must exit back to the application. On resumption, we reprocess * the marker. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" typedef enum { /* JPEG marker codes */ M_SOF0 = 0xc0, M_SOF1 = 0xc1, M_SOF2 = 0xc2, M_SOF3 = 0xc3, M_SOF5 = 0xc5, M_SOF6 = 0xc6, M_SOF7 = 0xc7, M_JPG = 0xc8, M_SOF9 = 0xc9, M_SOF10 = 0xca, M_SOF11 = 0xcb, M_SOF13 = 0xcd, M_SOF14 = 0xce, M_SOF15 = 0xcf, M_DHT = 0xc4, M_DAC = 0xcc, M_RST0 = 0xd0, M_RST1 = 0xd1, M_RST2 = 0xd2, M_RST3 = 0xd3, M_RST4 = 0xd4, M_RST5 = 0xd5, M_RST6 = 0xd6, M_RST7 = 0xd7, M_SOI = 0xd8, M_EOI = 0xd9, M_SOS = 0xda, M_DQT = 0xdb, M_DNL = 0xdc, M_DRI = 0xdd, M_DHP = 0xde, M_EXP = 0xdf, M_APP0 = 0xe0, M_APP1 = 0xe1, M_APP2 = 0xe2, M_APP3 = 0xe3, M_APP4 = 0xe4, M_APP5 = 0xe5, M_APP6 = 0xe6, M_APP7 = 0xe7, M_APP8 = 0xe8, M_APP9 = 0xe9, M_APP10 = 0xea, M_APP11 = 0xeb, M_APP12 = 0xec, M_APP13 = 0xed, M_APP14 = 0xee, M_APP15 = 0xef, M_JPG0 = 0xf0, M_JPG13 = 0xfd, M_COM = 0xfe, M_TEM = 0x01, M_ERROR = 0x100 } JPEG_MARKER; /* * Macros for fetching data from the data source module. * * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect * the current restart point; we update them only when we have reached a * suitable place to restart if a suspension occurs. */ /* Declare and initialize local copies of input pointer/count */ #define INPUT_VARS(cinfo) \ struct jpeg_source_mgr * datasrc = (cinfo)->src; \ const JOCTET * next_input_byte = datasrc->next_input_byte; \ size_t bytes_in_buffer = datasrc->bytes_in_buffer /* Unload the local copies --- do this only at a restart boundary */ #define INPUT_SYNC(cinfo) \ ( datasrc->next_input_byte = next_input_byte, \ datasrc->bytes_in_buffer = bytes_in_buffer ) /* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */ #define INPUT_RELOAD(cinfo) \ ( next_input_byte = datasrc->next_input_byte, \ bytes_in_buffer = datasrc->bytes_in_buffer ) /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available. * Note we do *not* do INPUT_SYNC before calling fill_input_buffer, * but we must reload the local copies after a successful fill. */ #define MAKE_BYTE_AVAIL(cinfo,action) \ if (bytes_in_buffer == 0) { \ if (! (*datasrc->fill_input_buffer) (cinfo)) \ { action; } \ INPUT_RELOAD(cinfo); \ } \ bytes_in_buffer-- /* Read a byte into variable V. * If must suspend, take the specified action (typically "return FALSE"). */ #define INPUT_BYTE(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo,V,action) \ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ MAKE_BYTE_AVAIL(cinfo,action); \ V += GETJOCTET(*next_input_byte++); ) /* * Routines to process JPEG markers. * * Entry condition: JPEG marker itself has been read and its code saved * in cinfo->unread_marker; input restart point is just after the marker. * * Exit: if return TRUE, have read and processed any parameters, and have * updated the restart point to point after the parameters. * If return FALSE, was forced to suspend before reaching end of * marker parameters; restart point has not been moved. Same routine * will be called again after application supplies more input data. * * This approach to suspension assumes that all of a marker's parameters can * fit into a single input bufferload. This should hold for "normal" * markers. Some COM/APPn markers might have large parameter segments, * but we use skip_input_data to get past those, and thereby put the problem * on the source manager's shoulders. * * Note that we don't bother to avoid duplicate trace messages if a * suspension occurs within marker parameters. Other side effects * require more care. */ LOCAL boolean get_soi (j_decompress_ptr cinfo) /* Process an SOI marker */ { int i; TRACEMS(cinfo, 1, JTRC_SOI); if (cinfo->marker->saw_SOI) ERREXIT(cinfo, JERR_SOI_DUPLICATE); /* Reset all parameters that are defined to be reset by SOI */ for (i = 0; i < NUM_ARITH_TBLS; i++) { cinfo->arith_dc_L[i] = 0; cinfo->arith_dc_U[i] = 1; cinfo->arith_ac_K[i] = 5; } cinfo->restart_interval = 0; /* Set initial assumptions for colorspace etc */ cinfo->jpeg_color_space = JCS_UNKNOWN; cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */ cinfo->saw_JFIF_marker = FALSE; cinfo->density_unit = 0; /* set default JFIF APP0 values */ cinfo->X_density = 1; cinfo->Y_density = 1; cinfo->saw_Adobe_marker = FALSE; cinfo->Adobe_transform = 0; cinfo->marker->saw_SOI = TRUE; return TRUE; } LOCAL boolean get_sof (j_decompress_ptr cinfo) /* Process a SOFn marker */ { INT32 length; int c, ci; jpeg_component_info * compptr; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE); INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE); INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE); INPUT_BYTE(cinfo, cinfo->num_components, return FALSE); length -= 8; TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker, (int) cinfo->image_width, (int) cinfo->image_height, cinfo->num_components); if (cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOF_DUPLICATE); /* We don't support files in which the image height is initially specified */ /* as 0 and is later redefined by DNL. As long as we have to check that, */ /* might as well have a general sanity check. */ if (cinfo->image_height <= 0 || cinfo->image_width <= 0 || cinfo->num_components <= 0) ERREXIT(cinfo, JERR_EMPTY_IMAGE); /* Make sure image isn't bigger than I can handle */ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, JPEG_MAX_DIMENSION); /* For now, precision must match compiled-in value... */ if (cinfo->data_precision != BITS_IN_JSAMPLE) ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); /* Check that number of components won't exceed internal array sizes */ if (cinfo->num_components > MAX_COMPONENTS) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, MAX_COMPONENTS); if (length != (cinfo->num_components * 3)) ERREXIT(cinfo, JERR_BAD_LENGTH); if (cinfo->comp_info == NULL) /* do only once, even if suspend */ cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->num_components * SIZEOF(jpeg_component_info)); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { compptr->component_index = ci; INPUT_BYTE(cinfo, compptr->component_id, return FALSE); INPUT_BYTE(cinfo, c, return FALSE); compptr->h_samp_factor = (c >> 4) & 15; compptr->v_samp_factor = (c ) & 15; INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE); TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT, compptr->component_id, compptr->h_samp_factor, compptr->v_samp_factor, compptr->quant_tbl_no); } cinfo->marker->saw_SOF = TRUE; INPUT_SYNC(cinfo); return TRUE; } LOCAL boolean get_sos (j_decompress_ptr cinfo) /* Process a SOS marker */ { INT32 length; int i, ci, n, c, cc; jpeg_component_info * compptr; INPUT_VARS(cinfo); if (! cinfo->marker->saw_SOF) ERREXIT(cinfo, JERR_SOS_NO_SOF); INPUT_2BYTES(cinfo, length, return FALSE); INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */ if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN) ERREXIT(cinfo, JERR_BAD_LENGTH); TRACEMS1(cinfo, 1, JTRC_SOS, n); cinfo->comps_in_scan = n; /* Collect the component-spec parameters */ for (i = 0; i < n; i++) { INPUT_BYTE(cinfo, cc, return FALSE); INPUT_BYTE(cinfo, c, return FALSE); for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (cc == compptr->component_id) goto id_found; } ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc); id_found: cinfo->cur_comp_info[i] = compptr; compptr->dc_tbl_no = (c >> 4) & 15; compptr->ac_tbl_no = (c ) & 15; TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc, compptr->dc_tbl_no, compptr->ac_tbl_no); } /* Collect the additional scan parameters Ss, Se, Ah/Al */ INPUT_BYTE(cinfo, c, return FALSE); if (c != 0) ERREXIT(cinfo, JERR_NOT_SEQUENTIAL); INPUT_BYTE(cinfo, c, return FALSE); if (c != DCTSIZE2-1) ERREXIT(cinfo, JERR_NOT_SEQUENTIAL); INPUT_BYTE(cinfo, c, return FALSE); if (c != 0) ERREXIT(cinfo, JERR_NOT_SEQUENTIAL); /* Prepare to scan data & restart markers */ cinfo->marker->next_restart_num = 0; INPUT_SYNC(cinfo); return TRUE; } METHODDEF boolean get_app0 (j_decompress_ptr cinfo) /* Process an APP0 marker */ { #define JFIF_LEN 14 INT32 length; UINT8 b[JFIF_LEN]; int buffp; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; /* See if a JFIF APP0 marker is present */ if (length >= JFIF_LEN) { for (buffp = 0; buffp < JFIF_LEN; buffp++) INPUT_BYTE(cinfo, b[buffp], return FALSE); length -= JFIF_LEN; if (b[0]==0x4A && b[1]==0x46 && b[2]==0x49 && b[3]==0x46 && b[4]==0) { /* Found JFIF APP0 marker: check version */ /* Major version must be 1 */ if (b[5] != 1) ERREXIT2(cinfo, JERR_JFIF_MAJOR, b[5], b[6]); /* Minor version should be 0..2, but try to process anyway if newer */ if (b[6] > 2) TRACEMS2(cinfo, 1, JTRC_JFIF_MINOR, b[5], b[6]); /* Save info */ cinfo->saw_JFIF_marker = TRUE; cinfo->density_unit = b[7]; cinfo->X_density = (b[8] << 8) + b[9]; cinfo->Y_density = (b[10] << 8) + b[11]; TRACEMS3(cinfo, 1, JTRC_JFIF, cinfo->X_density, cinfo->Y_density, cinfo->density_unit); if (b[12] | b[13]) TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL, b[12], b[13]); if (length != ((INT32) b[12] * (INT32) b[13] * (INT32) 3)) TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) length); } else { /* Start of APP0 does not match "JFIF" */ TRACEMS1(cinfo, 1, JTRC_APP0, (int) length + JFIF_LEN); } } else { /* Too short to be JFIF marker */ TRACEMS1(cinfo, 1, JTRC_APP0, (int) length); } INPUT_SYNC(cinfo); if (length > 0) /* skip any remaining data -- could be lots */ (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } METHODDEF boolean get_app14 (j_decompress_ptr cinfo) /* Process an APP14 marker */ { #define ADOBE_LEN 12 INT32 length; UINT8 b[ADOBE_LEN]; int buffp; unsigned int version, flags0, flags1, transform; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; /* See if an Adobe APP14 marker is present */ if (length >= ADOBE_LEN) { for (buffp = 0; buffp < ADOBE_LEN; buffp++) INPUT_BYTE(cinfo, b[buffp], return FALSE); length -= ADOBE_LEN; if (b[0]==0x41 && b[1]==0x64 && b[2]==0x6F && b[3]==0x62 && b[4]==0x65) { /* Found Adobe APP14 marker */ version = (b[5] << 8) + b[6]; flags0 = (b[7] << 8) + b[8]; flags1 = (b[9] << 8) + b[10]; transform = b[11]; TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform); cinfo->saw_Adobe_marker = TRUE; cinfo->Adobe_transform = (UINT8) transform; } else { /* Start of APP14 does not match "Adobe" */ TRACEMS1(cinfo, 1, JTRC_APP14, (int) length + ADOBE_LEN); } } else { /* Too short to be Adobe marker */ TRACEMS1(cinfo, 1, JTRC_APP14, (int) length); } INPUT_SYNC(cinfo); if (length > 0) /* skip any remaining data -- could be lots */ (*cinfo->src->skip_input_data) (cinfo, (long) length); return TRUE; } LOCAL boolean get_dac (j_decompress_ptr cinfo) /* Process a DAC marker */ { INT32 length; int index, val; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { INPUT_BYTE(cinfo, index, return FALSE); INPUT_BYTE(cinfo, val, return FALSE); length -= 2; TRACEMS2(cinfo, 1, JTRC_DAC, index, val); if (index < 0 || index >= (2*NUM_ARITH_TBLS)) ERREXIT1(cinfo, JERR_DAC_INDEX, index); if (index >= NUM_ARITH_TBLS) { /* define AC table */ cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val; } else { /* define DC table */ cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F); cinfo->arith_dc_U[index] = (UINT8) (val >> 4); if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index]) ERREXIT1(cinfo, JERR_DAC_VALUE, val); } } INPUT_SYNC(cinfo); return TRUE; } LOCAL boolean get_dht (j_decompress_ptr cinfo) /* Process a DHT marker */ { INT32 length; UINT8 bits[17]; UINT8 huffval[256]; int i, index, count; JHUFF_TBL **htblptr; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { INPUT_BYTE(cinfo, index, return FALSE); TRACEMS1(cinfo, 1, JTRC_DHT, index); bits[0] = 0; count = 0; for (i = 1; i <= 16; i++) { INPUT_BYTE(cinfo, bits[i], return FALSE); count += bits[i]; } length -= 1 + 16; TRACEMS8(cinfo, 2, JTRC_HUFFBITS, bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7], bits[8]); TRACEMS8(cinfo, 2, JTRC_HUFFBITS, bits[9], bits[10], bits[11], bits[12], bits[13], bits[14], bits[15], bits[16]); if (count > 256 || ((INT32) count) > length) ERREXIT(cinfo, JERR_DHT_COUNTS); for (i = 0; i < count; i++) INPUT_BYTE(cinfo, huffval[i], return FALSE); length -= count; if (index & 0x10) { /* AC table definition */ index -= 0x10; htblptr = &cinfo->ac_huff_tbl_ptrs[index]; } else { /* DC table definition */ htblptr = &cinfo->dc_huff_tbl_ptrs[index]; } if (index < 0 || index >= NUM_HUFF_TBLS) ERREXIT1(cinfo, JERR_DHT_INDEX, index); if (*htblptr == NULL) *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval)); } INPUT_SYNC(cinfo); return TRUE; } LOCAL boolean get_dqt (j_decompress_ptr cinfo) /* Process a DQT marker */ { INT32 length; int n, i, prec; unsigned int tmp; JQUANT_TBL *quant_ptr; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); length -= 2; while (length > 0) { INPUT_BYTE(cinfo, n, return FALSE); prec = n >> 4; n &= 0x0F; TRACEMS2(cinfo, 1, JTRC_DQT, n, prec); if (n >= NUM_QUANT_TBLS) ERREXIT1(cinfo, JERR_DQT_INDEX, n); if (cinfo->quant_tbl_ptrs[n] == NULL) cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo); quant_ptr = cinfo->quant_tbl_ptrs[n]; for (i = 0; i < DCTSIZE2; i++) { if (prec) INPUT_2BYTES(cinfo, tmp, return FALSE); else INPUT_BYTE(cinfo, tmp, return FALSE); quant_ptr->quantval[i] = (UINT16) tmp; } for (i = 0; i < DCTSIZE2; i += 8) { TRACEMS8(cinfo, 2, JTRC_QUANTVALS, quant_ptr->quantval[i ], quant_ptr->quantval[i+1], quant_ptr->quantval[i+2], quant_ptr->quantval[i+3], quant_ptr->quantval[i+4], quant_ptr->quantval[i+5], quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]); } length -= DCTSIZE2+1; if (prec) length -= DCTSIZE2; } INPUT_SYNC(cinfo); return TRUE; } LOCAL boolean get_dri (j_decompress_ptr cinfo) /* Process a DRI marker */ { INT32 length; unsigned int tmp; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); if (length != 4) ERREXIT(cinfo, JERR_BAD_LENGTH); INPUT_2BYTES(cinfo, tmp, return FALSE); TRACEMS1(cinfo, 1, JTRC_DRI, tmp); cinfo->restart_interval = tmp; INPUT_SYNC(cinfo); return TRUE; } METHODDEF boolean skip_variable (j_decompress_ptr cinfo) /* Skip over an unknown or uninteresting variable-length marker */ { INT32 length; INPUT_VARS(cinfo); INPUT_2BYTES(cinfo, length, return FALSE); TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length); INPUT_SYNC(cinfo); /* do before skip_input_data */ (*cinfo->src->skip_input_data) (cinfo, (long) length - 2L); return TRUE; } /* * Find the next JPEG marker, save it in cinfo->unread_marker. * Returns FALSE if had to suspend before reaching a marker; * in that case cinfo->unread_marker is unchanged. * * Note that the result might not be a valid marker code, * but it will never be 0 or FF. */ LOCAL boolean next_marker (j_decompress_ptr cinfo) { int c; INPUT_VARS(cinfo); for (;;) { INPUT_BYTE(cinfo, c, return FALSE); /* Skip any non-FF bytes. * This may look a bit inefficient, but it will not occur in a valid file. * We sync after each discarded byte so that a suspending data source * can discard the byte from its buffer. */ while (c != 0xFF) { cinfo->marker->discarded_bytes++; INPUT_SYNC(cinfo); INPUT_BYTE(cinfo, c, return FALSE); } /* This loop swallows any duplicate FF bytes. Extra FFs are legal as * pad bytes, so don't count them in discarded_bytes. We assume there * will not be so many consecutive FF bytes as to overflow a suspending * data source's input buffer. */ do { INPUT_BYTE(cinfo, c, return FALSE); } while (c == 0xFF); if (c != 0) break; /* found a valid marker, exit loop */ /* Reach here if we found a stuffed-zero data sequence (FF/00). * Discard it and loop back to try again. */ cinfo->marker->discarded_bytes += 2; INPUT_SYNC(cinfo); } if (cinfo->marker->discarded_bytes != 0) { WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c); cinfo->marker->discarded_bytes = 0; } cinfo->unread_marker = c; INPUT_SYNC(cinfo); return TRUE; } LOCAL boolean first_marker (j_decompress_ptr cinfo) /* Like next_marker, but used to obtain the initial SOI marker. */ /* For this marker, we do not allow preceding garbage or fill; otherwise, * we might well scan an entire input file before realizing it ain't JPEG. * If an application wants to process non-JFIF files, it must seek to the * SOI before calling the JPEG library. */ { int c, c2; INPUT_VARS(cinfo); INPUT_BYTE(cinfo, c, return FALSE); INPUT_BYTE(cinfo, c2, return FALSE); if (c != 0xFF || c2 != (int) M_SOI) ERREXIT2(cinfo, JERR_NO_SOI, c, c2); cinfo->unread_marker = c2; INPUT_SYNC(cinfo); return TRUE; } /* * Read markers until SOS or EOI. * * Returns same codes as are defined for jpeg_read_header, * but HEADER_OK and HEADER_TABLES_ONLY merely indicate which marker type * stopped the scan --- they do not necessarily mean the file is valid. */ METHODDEF int read_markers (j_decompress_ptr cinfo) { /* Outer loop repeats once for each marker. */ for (;;) { /* Collect the marker proper, unless we already did. */ /* NB: first_marker() enforces the requirement that SOI appear first. */ if (cinfo->unread_marker == 0) { if (! cinfo->marker->saw_SOI) { if (! first_marker(cinfo)) return JPEG_SUSPENDED; } else { if (! next_marker(cinfo)) return JPEG_SUSPENDED; } } /* At this point cinfo->unread_marker contains the marker code and the * input point is just past the marker proper, but before any parameters. * A suspension will cause us to return with this state still true. */ switch (cinfo->unread_marker) { case M_SOI: if (! get_soi(cinfo)) return JPEG_SUSPENDED; break; case M_SOF0: /* Baseline */ case M_SOF1: /* Extended sequential, Huffman */ cinfo->arith_code = FALSE; if (! get_sof(cinfo)) return JPEG_SUSPENDED; break; case M_SOF9: /* Extended sequential, arithmetic */ cinfo->arith_code = TRUE; if (! get_sof(cinfo)) return JPEG_SUSPENDED; break; /* Currently unsupported SOFn types */ case M_SOF2: /* Progressive, Huffman */ case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_JPG: /* Reserved for JPEG extensions */ case M_SOF10: /* Progressive, arithmetic */ case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker); break; case M_SOS: if (! get_sos(cinfo)) return JPEG_SUSPENDED; cinfo->unread_marker = 0; /* processed the marker */ return JPEG_HEADER_OK; /* return value for SOS found */ case M_EOI: TRACEMS(cinfo, 1, JTRC_EOI); cinfo->unread_marker = 0; /* processed the marker */ return JPEG_HEADER_TABLES_ONLY; /* return value for EOI found */ case M_DAC: if (! get_dac(cinfo)) return JPEG_SUSPENDED; break; case M_DHT: if (! get_dht(cinfo)) return JPEG_SUSPENDED; break; case M_DQT: if (! get_dqt(cinfo)) return JPEG_SUSPENDED; break; case M_DRI: if (! get_dri(cinfo)) return JPEG_SUSPENDED; break; case M_APP0: case M_APP1: case M_APP2: case M_APP3: case M_APP4: case M_APP5: case M_APP6: case M_APP7: case M_APP8: case M_APP9: case M_APP10: case M_APP11: case M_APP12: case M_APP13: case M_APP14: case M_APP15: if (! (*cinfo->marker->process_APPn[cinfo->unread_marker - (int) M_APP0]) (cinfo)) return JPEG_SUSPENDED; break; case M_COM: if (! (*cinfo->marker->process_COM) (cinfo)) return JPEG_SUSPENDED; break; case M_RST0: /* these are all parameterless */ case M_RST1: case M_RST2: case M_RST3: case M_RST4: case M_RST5: case M_RST6: case M_RST7: case M_TEM: TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker); break; default: /* must be DNL, DHP, EXP, JPGn, or RESn */ if (! skip_variable(cinfo)) return JPEG_SUSPENDED; break; } /* Successfully processed marker, so reset state variable */ cinfo->unread_marker = 0; } /* end loop */ } /* * Read a restart marker, which is expected to appear next in the datastream; * if the marker is not there, take appropriate recovery action. * Returns FALSE if suspension is required. * * This is called by the entropy decoder after it has read an appropriate * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder * has already read a marker from the data source. Under normal conditions * cinfo->unread_marker will be reset to 0 before returning; if not reset, * it holds a marker which the decoder will be unable to read past. */ METHODDEF boolean read_restart_marker (j_decompress_ptr cinfo) { /* Obtain a marker unless we already did. */ /* Note that next_marker will complain if it skips any data. */ if (cinfo->unread_marker == 0) { if (! next_marker(cinfo)) return FALSE; } if (cinfo->unread_marker == ((int) M_RST0 + cinfo->marker->next_restart_num)) { /* Normal case --- swallow the marker and let entropy decoder continue */ TRACEMS1(cinfo, 2, JTRC_RST, cinfo->marker->next_restart_num); cinfo->unread_marker = 0; } else { /* Uh-oh, the restart markers have been messed up. */ /* Let the data source manager determine how to resync. */ if (! (*cinfo->src->resync_to_restart) (cinfo)) return FALSE; } /* Update next-restart state */ cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7; return TRUE; } /* * This is the default resync_to_restart method for data source managers * to use if they don't have any better approach. Some data source managers * may be able to back up, or may have additional knowledge about the data * which permits a more intelligent recovery strategy; such managers would * presumably supply their own resync method. * * read_restart_marker calls resync_to_restart if it finds a marker other than * the restart marker it was expecting. (This code is *not* used unless * a nonzero restart interval has been declared.) cinfo->unread_marker is * the marker code actually found (might be anything, except 0 or FF). * The desired restart marker is indicated by cinfo->marker->next_restart_num. * This routine is supposed to apply whatever error recovery strategy seems * appropriate in order to position the input stream to the next data segment. * Note that cinfo->unread_marker is treated as a marker appearing before * the current data-source input point; usually it should be reset to zero * before returning. * Returns FALSE if suspension is required. * * This implementation is substantially constrained by wanting to treat the * input as a data stream; this means we can't back up. Therefore, we have * only the following actions to work with: * 1. Simply discard the marker and let the entropy decoder resume at next * byte of file. * 2. Read forward until we find another marker, discarding intervening * data. (In theory we could look ahead within the current bufferload, * without having to discard data if we don't find the desired marker. * This idea is not implemented here, in part because it makes behavior * dependent on buffer size and chance buffer-boundary positions.) * 3. Leave the marker unread (by failing to zero cinfo->unread_marker). * This will cause the entropy decoder to process an empty data segment, * inserting dummy zeroes, and then we will reprocess the marker. * * #2 is appropriate if we think the desired marker lies ahead, while #3 is * appropriate if the found marker is a future restart marker (indicating * that we have missed the desired restart marker, probably because it got * corrupted). * We apply #2 or #3 if the found marker is a restart marker no more than * two counts behind or ahead of the expected one. We also apply #2 if the * found marker is not a legal JPEG marker code (it's certainly bogus data). * If the found marker is a restart marker more than 2 counts away, we do #1 * (too much risk that the marker is erroneous; with luck we will be able to * resync at some future point). * For any valid non-restart JPEG marker, we apply #3. This keeps us from * overrunning the end of a scan. An implementation limited to single-scan * files might find it better to apply #2 for markers other than EOI, since * any other marker would have to be bogus data in that case. */ GLOBAL boolean jpeg_resync_to_restart (j_decompress_ptr cinfo) { int marker = cinfo->unread_marker; int desired = cinfo->marker->next_restart_num; int action = 1; /* Always put up a warning. */ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired); /* Outer loop handles repeated decision after scanning forward. */ for (;;) { if (marker < (int) M_SOF0) action = 2; /* invalid marker */ else if (marker < (int) M_RST0 || marker > (int) M_RST7) action = 3; /* valid non-restart marker */ else { if (marker == ((int) M_RST0 + ((desired+1) & 7)) || marker == ((int) M_RST0 + ((desired+2) & 7))) action = 3; /* one of the next two expected restarts */ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) || marker == ((int) M_RST0 + ((desired-2) & 7))) action = 2; /* a prior restart, so advance */ else action = 1; /* desired restart or too far away */ } TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action); switch (action) { case 1: /* Discard marker and let entropy decoder resume processing. */ cinfo->unread_marker = 0; return TRUE; case 2: /* Scan to the next marker, and repeat the decision loop. */ if (! next_marker(cinfo)) return FALSE; marker = cinfo->unread_marker; break; case 3: /* Return without advancing past this marker. */ /* Entropy decoder will be forced to process an empty segment. */ return TRUE; } } /* end loop */ } /* * Reset marker processing state to begin a fresh datastream. */ METHODDEF void reset_marker_reader (j_decompress_ptr cinfo) { cinfo->unread_marker = 0; /* no pending marker */ cinfo->marker->saw_SOI = FALSE; /* set internal state too */ cinfo->marker->saw_SOF = FALSE; cinfo->marker->discarded_bytes = 0; cinfo->comp_info = NULL; /* until allocated by get_sof */ } /* * Initialize the marker reader module. */ GLOBAL void jinit_marker_reader (j_decompress_ptr cinfo) { int i; /* Create subobject in permanent pool */ if (cinfo->marker == NULL) { /* first time for this JPEG object? */ cinfo->marker = (struct jpeg_marker_reader *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(struct jpeg_marker_reader)); } /* Initialize method pointers */ cinfo->marker->reset_marker_reader = reset_marker_reader; cinfo->marker->read_markers = read_markers; cinfo->marker->read_restart_marker = read_restart_marker; cinfo->marker->process_COM = skip_variable; for (i = 0; i < 16; i++) cinfo->marker->process_APPn[i] = skip_variable; cinfo->marker->process_APPn[0] = get_app0; cinfo->marker->process_APPn[14] = get_app14; /* Reset marker processing state */ reset_marker_reader(cinfo); } \ No newline at end of file diff --git a/Independent JPEG Group/jdmaster.c b/Independent JPEG Group/jdmaster.c new file mode 100644 index 0000000..f3560c4 --- /dev/null +++ b/Independent JPEG Group/jdmaster.c @@ -0,0 +1 @@ +/* * jdmaster.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains master control logic for the JPEG decompressor. * These routines are concerned with selecting the modules to be executed * and with determining the number of passes and the work to be done in each * pass. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private state */ typedef struct { struct jpeg_decomp_master pub; /* public fields */ int pass_number; /* probably need more complex state... */ boolean really_two_pass; /* T if using full two-pass quantization */ } my_decomp_master; typedef my_decomp_master * my_master_ptr; /* * Support routines that do various essential calculations. * * jpeg_calc_output_dimensions is exported for possible use by application. * Hence it mustn't do anything that can't be done twice. */ GLOBAL void jpeg_calc_output_dimensions (j_decompress_ptr cinfo) /* Do computations that are needed before master selection phase */ { int ci; jpeg_component_info *compptr; /* Compute maximum sampling factors; check factor validity */ cinfo->max_h_samp_factor = 1; cinfo->max_v_samp_factor = 1; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) ERREXIT(cinfo, JERR_BAD_SAMPLING); cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, compptr->h_samp_factor); cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, compptr->v_samp_factor); } /* Compute actual output image dimensions and DCT scaling choices. */ #ifdef IDCT_SCALING_SUPPORTED if (cinfo->scale_num * 8 <= cinfo->scale_denom) { /* Provide 1/8 scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, 8L); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, 8L); cinfo->min_DCT_scaled_size = 1; } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) { /* Provide 1/4 scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, 4L); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, 4L); cinfo->min_DCT_scaled_size = 2; } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) { /* Provide 1/2 scaling */ cinfo->output_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, 2L); cinfo->output_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, 2L); cinfo->min_DCT_scaled_size = 4; } else { /* Provide 1/1 scaling */ cinfo->output_width = cinfo->image_width; cinfo->output_height = cinfo->image_height; cinfo->min_DCT_scaled_size = DCTSIZE; } /* In selecting the actual DCT scaling for each component, we try to * scale up the chroma components via IDCT scaling rather than upsampling. * This saves time if the upsampler gets to use 1:1 scaling. * Note this code assumes that the supported DCT scalings are powers of 2. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { int ssize = cinfo->min_DCT_scaled_size; while (ssize < DCTSIZE && (compptr->h_samp_factor * ssize * 2 <= cinfo->max_h_samp_factor * cinfo->min_DCT_scaled_size) && (compptr->v_samp_factor * ssize * 2 <= cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size)) { ssize = ssize * 2; } compptr->DCT_scaled_size = ssize; } #else /* !IDCT_SCALING_SUPPORTED */ /* Hardwire it to "no scaling" */ cinfo->output_width = cinfo->image_width; cinfo->output_height = cinfo->image_height; cinfo->min_DCT_scaled_size = DCTSIZE; for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { compptr->DCT_scaled_size = DCTSIZE; } #endif /* IDCT_SCALING_SUPPORTED */ /* Upsample controller really ought to be setting this... */ cinfo->rec_outbuf_height = 1; /* Report number of components in selected colorspace. */ /* Probably this should be in the color conversion module... */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: cinfo->out_color_components = 1; break; case JCS_RGB: case JCS_YCbCr: cinfo->out_color_components = 3; break; case JCS_CMYK: case JCS_YCCK: cinfo->out_color_components = 4; break; default: /* else must be same colorspace as in file */ cinfo->out_color_components = cinfo->num_components; break; } cinfo->output_components = (cinfo->quantize_colors ? 1 : cinfo->out_color_components); /* Compute various sampling-related dimensions. * Some of these are of interest to the application if it is dealing with * "raw" (not upsampled) output, so we do the calculations here. */ /* Compute dimensions of components */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Size in DCT blocks */ compptr->width_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->height_in_blocks = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, (long) (cinfo->max_v_samp_factor * DCTSIZE)); /* Size in samples, after IDCT scaling */ compptr->downsampled_width = (JDIMENSION) jdiv_round_up((long) cinfo->image_width * (long) (compptr->h_samp_factor * compptr->DCT_scaled_size), (long) (cinfo->max_h_samp_factor * DCTSIZE)); compptr->downsampled_height = (JDIMENSION) jdiv_round_up((long) cinfo->image_height * (long) (compptr->v_samp_factor * compptr->DCT_scaled_size), (long) (cinfo->max_v_samp_factor * DCTSIZE)); /* Mark component needed, until color conversion says otherwise */ compptr->component_needed = TRUE; } /* Compute number of fully interleaved MCU rows (number of times that * main controller will call coefficient controller). */ cinfo->total_iMCU_rows = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); } LOCAL void per_scan_setup (j_decompress_ptr cinfo) /* Do computations that are needed before processing a JPEG scan */ /* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */ { int ci, mcublks; JDIMENSION tmp; jpeg_component_info *compptr; if (cinfo->comps_in_scan == 1) { /* Noninterleaved (single-component) scan */ compptr = cinfo->cur_comp_info[0]; /* Overall image size in MCUs */ cinfo->MCUs_per_row = compptr->width_in_blocks; cinfo->MCU_rows_in_scan = compptr->height_in_blocks; /* For noninterleaved scan, always one block per MCU */ compptr->MCU_width = 1; compptr->MCU_height = 1; compptr->MCU_blocks = 1; compptr->MCU_sample_width = compptr->DCT_scaled_size; compptr->last_col_width = 1; compptr->last_row_height = 1; /* Prepare array describing MCU composition */ cinfo->blocks_in_MCU = 1; cinfo->MCU_membership[0] = 0; } else { /* Interleaved (multi-component) scan */ if (cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, MAX_COMPS_IN_SCAN); /* Overall image size in MCUs */ cinfo->MCUs_per_row = (JDIMENSION) jdiv_round_up((long) cinfo->image_width, (long) (cinfo->max_h_samp_factor*DCTSIZE)); cinfo->MCU_rows_in_scan = (JDIMENSION) jdiv_round_up((long) cinfo->image_height, (long) (cinfo->max_v_samp_factor*DCTSIZE)); cinfo->blocks_in_MCU = 0; for (ci = 0; ci < cinfo->comps_in_scan; ci++) { compptr = cinfo->cur_comp_info[ci]; /* Sampling factors give # of blocks of component in each MCU */ compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_scaled_size; /* Figure number of non-dummy blocks in last MCU column & row */ tmp = compptr->width_in_blocks % compptr->MCU_width; if (tmp == 0) tmp = compptr->MCU_width; compptr->last_col_width = (int) tmp; tmp = compptr->height_in_blocks % compptr->MCU_height; if (tmp == 0) tmp = compptr->MCU_height; compptr->last_row_height = (int) tmp; /* Prepare array describing MCU composition */ mcublks = compptr->MCU_blocks; if (cinfo->blocks_in_MCU + mcublks > MAX_BLOCKS_IN_MCU) ERREXIT(cinfo, JERR_BAD_MCU_SIZE); while (mcublks-- > 0) { cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; } } } } /* * Several decompression processes need to range-limit values to the range * 0..MAXJSAMPLE; the input value may fall somewhat outside this range * due to noise introduced by quantization, roundoff error, etc. These * processes are inner loops and need to be as fast as possible. On most * machines, particularly CPUs with pipelines or instruction prefetch, * a (subscript-check-less) C table lookup * x = sample_range_limit[x]; * is faster than explicit tests * if (x < 0) x = 0; * else if (x > MAXJSAMPLE) x = MAXJSAMPLE; * These processes all use a common table prepared by the routine below. * * For most steps we can mathematically guarantee that the initial value * of x is within MAXJSAMPLE+1 of the legal range, so a table running from * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial * limiting step (just after the IDCT), a wildly out-of-range value is * possible if the input data is corrupt. To avoid any chance of indexing * off the end of memory and getting a bad-pointer trap, we perform the * post-IDCT limiting thus: * x = range_limit[x & MASK]; * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit * samples. Under normal circumstances this is more than enough range and * a correct output will be generated; with bogus input data the mask will * cause wraparound, and we will safely generate a bogus output. * For the post-IDCT step, we want to convert the data from signed to unsigned * representation by adding CENTERJSAMPLE at the same time that we limit it. * So the post-IDCT limiting table ends up looking like this: * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE, * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times), * 0,1,...,CENTERJSAMPLE-1 * Negative inputs select values from the upper half of the table after * masking. * * We can save some space by overlapping the start of the post-IDCT table * with the simpler range limiting table. The post-IDCT table begins at * sample_range_limit + CENTERJSAMPLE. * * Note that the table is allocated in near data space on PCs; it's small * enough and used often enough to justify this. */ LOCAL void prepare_range_limit_table (j_decompress_ptr cinfo) /* Allocate and fill in the sample_range_limit table */ { JSAMPLE * table; int i; table = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE)); table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */ cinfo->sample_range_limit = table; /* First segment of "simple" table: limit[x] = 0 for x < 0 */ MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE)); /* Main part of "simple" table: limit[x] = x */ for (i = 0; i <= MAXJSAMPLE; i++) table[i] = (JSAMPLE) i; table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */ /* End of simple table, rest of first half of post-IDCT table */ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++) table[i] = MAXJSAMPLE; /* Second half of post-IDCT table */ MEMZERO(table + (2 * (MAXJSAMPLE+1)), (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE)); MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE), cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE)); } /* * Master selection of decompression modules. * This is done once at the start of processing an image. We determine * which modules will be used and give them appropriate initialization calls. * * Note that this is called only after jpeg_read_header has finished. * We therefore know what is in the SOF and (first) SOS markers. */ LOCAL void master_selection (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; jpeg_calc_output_dimensions(cinfo); prepare_range_limit_table(cinfo); master->pass_number = 0; master->really_two_pass = FALSE; master->pub.eoi_processed = FALSE; /* There's not a lot of smarts here right now, but it'll get more * complicated when we have multiple implementations available... */ /* Color quantizer selection */ if (cinfo->quantize_colors) { #ifdef QUANT_2PASS_SUPPORTED /* 2-pass quantizer only works in 3-component color space. * We use the "2-pass" code in a single pass if a colormap is given. */ if (cinfo->out_color_components != 3) cinfo->two_pass_quantize = FALSE; else if (cinfo->colormap != NULL) cinfo->two_pass_quantize = TRUE; #else /* Force 1-pass quantize if we don't have 2-pass code compiled. */ cinfo->two_pass_quantize = FALSE; #endif if (cinfo->two_pass_quantize) { #ifdef QUANT_2PASS_SUPPORTED if (cinfo->colormap == NULL) master->really_two_pass = TRUE; jinit_2pass_quantizer(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } else { #ifdef QUANT_1PASS_SUPPORTED jinit_1pass_quantizer(cinfo); #else ERREXIT(cinfo, JERR_NOT_COMPILED); #endif } } /* Post-processing: in particular, color conversion first */ jinit_color_deconverter(cinfo); jinit_upsampler(cinfo); jinit_d_post_controller(cinfo, master->really_two_pass); /* Inverse DCT */ jinit_inverse_dct(cinfo); /* Entropy decoding: either Huffman or arithmetic coding. */ if (cinfo->arith_code) { #ifdef D_ARITH_CODING_SUPPORTED jinit_arith_decoder(cinfo); #else ERREXIT(cinfo, JERR_ARITH_NOTIMPL); #endif } else jinit_huff_decoder(cinfo); jinit_d_coef_controller(cinfo, FALSE /* for now */); jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */); /* We can now tell the memory manager to allocate virtual arrays. */ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); } /* * Per-pass setup. * This is called at the beginning of each pass. We determine which modules * will be active during this pass and give them appropriate start_pass calls. * We also set is_last_pass to indicate whether any more passes will be * required. */ METHODDEF void prepare_for_pass (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; /* ???? JUST A QUICK CROCK FOR NOW ??? */ /* For now, handle only single interleaved input scan; */ /* we support two passes for color quantization. */ switch (master->pass_number) { case 0: /* Set up for data input pass */ per_scan_setup(cinfo); /* should do this only if an input pass?? */ master->pub.is_last_pass = ! master->really_two_pass; (*cinfo->cconvert->start_pass) (cinfo); (*cinfo->upsample->start_pass) (cinfo); if (cinfo->quantize_colors) (*cinfo->cquantize->start_pass) (cinfo, master->really_two_pass); (*cinfo->post->start_pass) (cinfo, (master->really_two_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); (*cinfo->idct->start_pass) (cinfo); (*cinfo->entropy->start_pass) (cinfo); (*cinfo->coef->start_pass) (cinfo, JBUF_PASS_THRU); (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); break; case 1: /* Final pass of 2-pass quantization */ master->pub.is_last_pass = TRUE; (*cinfo->cquantize->start_pass) (cinfo, FALSE); (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST); (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST); break; } } /* * Finish up at end of pass. */ METHODDEF void finish_pass (j_decompress_ptr cinfo) { my_master_ptr master = (my_master_ptr) cinfo->master; if (cinfo->quantize_colors) (*cinfo->cquantize->finish_pass) (cinfo); master->pass_number++; } /* * Initialize master decompression control. * This creates my own subrecord and also performs the master selection phase, * which causes other modules to create their subrecords. */ GLOBAL void jinit_master_decompress (j_decompress_ptr cinfo) { my_master_ptr master; master = (my_master_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_decomp_master)); cinfo->master = (struct jpeg_decomp_master *) master; master->pub.prepare_for_pass = prepare_for_pass; master->pub.finish_pass = finish_pass; master_selection(cinfo); } \ No newline at end of file diff --git a/Independent JPEG Group/jdpostct.c b/Independent JPEG Group/jdpostct.c new file mode 100644 index 0000000..0f2ac05 --- /dev/null +++ b/Independent JPEG Group/jdpostct.c @@ -0,0 +1 @@ +/* * jdpostct.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the decompression postprocessing controller. * This controller manages the upsampling, color conversion, and color * quantization/reduction steps; specifically, it controls the buffering * between upsample/color conversion and color quantization/reduction. * * If no color quantization/reduction is required, then this module has no * work to do, and it just hands off to the upsample/color conversion code. * An integrated upsample/convert/quantize process would replace this module * entirely. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Private buffer controller object */ typedef struct { struct jpeg_d_post_controller pub; /* public fields */ /* Color quantization source buffer: this holds output data from * the upsample/color conversion step to be passed to the quantizer. * For two-pass color quantization, we need a full-image buffer; * for one-pass operation, a strip buffer is sufficient. */ jvirt_sarray_ptr virtual; /* virtual array, or NULL if one-pass */ JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */ JDIMENSION strip_height; /* buffer size in rows */ /* for two-pass mode only: */ JDIMENSION starting_row; /* row # of first row in current strip */ JDIMENSION next_row; /* index of next row to fill/empty in strip */ } my_post_controller; typedef my_post_controller * my_post_ptr; /* Forward declarations */ METHODDEF void post_process_1pass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #ifdef QUANT_2PASS_SUPPORTED METHODDEF void post_process_prepass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); METHODDEF void post_process_2pass JPP((j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); #endif /* * Initialize for a processing pass. */ METHODDEF void start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode) { my_post_ptr post = (my_post_ptr) cinfo->post; switch (pass_mode) { case JBUF_PASS_THRU: if (cinfo->quantize_colors) { /* Single-pass processing with color quantization. */ post->pub.post_process_data = post_process_1pass; } else { /* For single-pass processing without color quantization, * I have no work to do; just call the upsampler directly. */ post->pub.post_process_data = cinfo->upsample->upsample; } break; #ifdef QUANT_2PASS_SUPPORTED case JBUF_SAVE_AND_PASS: /* First pass of 2-pass quantization */ if (post->virtual == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); post->pub.post_process_data = post_process_prepass; break; case JBUF_CRANK_DEST: /* Second pass of 2-pass quantization */ if (post->virtual == NULL) ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); post->pub.post_process_data = post_process_2pass; break; #endif /* QUANT_2PASS_SUPPORTED */ default: ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); break; } post->starting_row = post->next_row = 0; } /* * Process some data in the one-pass (strip buffer) case. * This is used for color precision reduction as well as one-pass quantization. */ METHODDEF void post_process_1pass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; /* Fill the buffer, but not more than what we can dump out in one go. */ /* Note we rely on the upsampler to detect bottom of image. */ max_rows = out_rows_avail - *out_row_ctr; if (max_rows > post->strip_height) max_rows = post->strip_height; num_rows = 0; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &num_rows, max_rows); /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; } #ifdef QUANT_2PASS_SUPPORTED /* * Process some data in the first pass of 2-pass quantization. */ METHODDEF void post_process_prepass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION old_next_row, num_rows; /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->virtual, post->starting_row, TRUE); } /* Upsample some data (up to a strip height's worth). */ old_next_row = post->next_row; (*cinfo->upsample->upsample) (cinfo, input_buf, in_row_group_ctr, in_row_groups_avail, post->buffer, &post->next_row, post->strip_height); /* Allow quantizer to scan new data. No data is emitted, */ /* but we advance out_row_ctr so outer loop can tell when we're done. */ if (post->next_row > old_next_row) { num_rows = post->next_row - old_next_row; (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row, NULL, (int) num_rows); *out_row_ctr += num_rows; } /* Advance if we filled the strip. */ if (post->next_row >= post->strip_height) { post->starting_row += post->strip_height; post->next_row = 0; } } /* * Process some data in the second pass of 2-pass quantization. */ METHODDEF void post_process_2pass (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_post_ptr post = (my_post_ptr) cinfo->post; JDIMENSION num_rows, max_rows; /* Reposition virtual buffer if at start of strip. */ if (post->next_row == 0) { post->buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, post->virtual, post->starting_row, FALSE); } /* Determine number of rows to emit. */ num_rows = post->strip_height - post->next_row; /* available in strip */ max_rows = out_rows_avail - *out_row_ctr; /* available in output area */ if (num_rows > max_rows) num_rows = max_rows; /* We have to check bottom of image here, can't depend on upsampler. */ max_rows = cinfo->output_height - post->starting_row; if (num_rows > max_rows) num_rows = max_rows; /* Quantize and emit data. */ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + post->next_row, output_buf + *out_row_ctr, (int) num_rows); *out_row_ctr += num_rows; /* Advance if we filled the strip. */ post->next_row += num_rows; if (post->next_row >= post->strip_height) { post->starting_row += post->strip_height; post->next_row = 0; } } #endif /* QUANT_2PASS_SUPPORTED */ /* * Initialize postprocessing controller. */ GLOBAL void jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer) { my_post_ptr post; post = (my_post_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_post_controller)); cinfo->post = (struct jpeg_d_post_controller *) post; post->pub.start_pass = start_pass_dpost; post->virtual = NULL; /* flag for no virtual arrays */ /* Create the quantization buffer, if needed */ if (cinfo->quantize_colors) { /* The buffer strip height is max_v_samp_factor, which is typically * an efficient number of rows for upsampling to return. * (In the presence of output rescaling, we might want to be smarter?) */ post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor; if (need_full_buffer) { /* Two-pass color quantization: need full-image storage. */ #ifdef QUANT_2PASS_SUPPORTED post->virtual = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, cinfo->output_height, post->strip_height); #else ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); #endif /* QUANT_2PASS_SUPPORTED */ } else { /* One-pass color quantization: just make a strip buffer. */ post->buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width * cinfo->out_color_components, post->strip_height); } } } \ No newline at end of file diff --git a/Independent JPEG Group/jdsample.c b/Independent JPEG Group/jdsample.c new file mode 100644 index 0000000..a384195 --- /dev/null +++ b/Independent JPEG Group/jdsample.c @@ -0,0 +1 @@ +/* * jdsample.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains upsampling routines. * * Upsampling input data is counted in "row groups". A row group * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size) * sample rows of each component. Upsampling will normally produce * max_v_samp_factor pixel rows from each row group (but this could vary * if the upsampler is applying a scale factor of its own). * * An excellent reference for image resampling is * Digital Image Warping, George Wolberg, 1990. * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* Pointer to routine to upsample a single component */ typedef JMETHOD(void, upsample1_ptr, (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)); /* Private subobject */ typedef struct { struct jpeg_upsampler pub; /* public fields */ /* Color conversion buffer. When using separate upsampling and color * conversion steps, this buffer holds one upsampled row group until it * has been color converted and output. * Note: we do not allocate any storage for component(s) which are full-size, * ie do not need rescaling. The corresponding entry of color_buf[] is * simply set to point to the input data array, thereby avoiding copying. */ JSAMPARRAY color_buf[MAX_COMPONENTS]; /* Per-component upsampling method pointers */ upsample1_ptr methods[MAX_COMPONENTS]; int next_row_out; /* counts rows emitted from color_buf */ JDIMENSION rows_to_go; /* counts rows remaining in image */ /* Height of an input row group for each component. */ int rowgroup_height[MAX_COMPONENTS]; /* These arrays save pixel expansion factors so that int_expand need not * recompute them each time. They are unused for other upsampling methods. */ UINT8 h_expand[MAX_COMPONENTS]; UINT8 v_expand[MAX_COMPONENTS]; } my_upsampler; typedef my_upsampler * my_upsample_ptr; /* * Initialize for an upsampling pass. */ METHODDEF void start_pass (j_decompress_ptr cinfo) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; /* Mark the conversion buffer empty */ upsample->next_row_out = cinfo->max_v_samp_factor; /* Initialize total-height counter for detecting bottom of image */ upsample->rows_to_go = cinfo->output_height; } /* * Control routine to do upsampling (and color conversion). * * In this version we upsample each component independently. * We upsample one row group into the conversion buffer, then apply * color conversion a row at a time. */ METHODDEF void sep_upsample (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; int ci; jpeg_component_info * compptr; JDIMENSION num_rows; /* Fill the conversion buffer, if it's empty */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) { for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Invoke per-component upsample method. Notice we pass a POINTER * to color_buf[ci], so that fullsize_upsample can change it. */ (*upsample->methods[ci]) (cinfo, compptr, input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]), upsample->color_buf + ci); } upsample->next_row_out = 0; } /* Color-convert and emit rows */ /* How many we have in the buffer: */ num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out); /* Not more than the distance to the end of the image. Need this test * in case the image height is not a multiple of max_v_samp_factor: */ if (num_rows > upsample->rows_to_go) num_rows = upsample->rows_to_go; /* And not more than what the client can accept: */ out_rows_avail -= *out_row_ctr; if (num_rows > out_rows_avail) num_rows = out_rows_avail; (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf, (JDIMENSION) upsample->next_row_out, output_buf + *out_row_ctr, (int) num_rows); /* Adjust counts */ *out_row_ctr += num_rows; upsample->rows_to_go -= num_rows; upsample->next_row_out += num_rows; /* When the buffer is emptied, declare this input row group consumed */ if (upsample->next_row_out >= cinfo->max_v_samp_factor) (*in_row_group_ctr)++; } /* * These are the routines invoked by sep_upsample to upsample pixel values * of a single component. One row group is processed per call. */ /* * For full-size components, we just make color_buf[ci] point at the * input buffer, and thus avoid copying any data. Note that this is * safe only because sep_upsample doesn't declare the input row group * "consumed" until we are done color converting and emitting it. */ METHODDEF void fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { *output_data_ptr = input_data; } /* * This is a no-op version used for "uninteresting" components. * These components will not be referenced by color conversion. */ METHODDEF void noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { *output_data_ptr = NULL; /* safety check */ } /* * This version handles any integral sampling ratios. * This is not used for typical JPEG files, so it need not be fast. * Nor, for that matter, is it particularly accurate: the algorithm is * simple replication of the input pixel onto the corresponding output * pixels. The hi-falutin sampling literature refers to this as a * "box filter". A box filter tends to introduce visible artifacts, * so if you are actually going to use 3:1 or 4:1 sampling ratios * you would be well advised to improve this code. */ METHODDEF void int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample; JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register JSAMPLE invalue; register int h; JSAMPROW outend; int h_expand, v_expand, v; int inrow, outrow; h_expand = upsample->h_expand[compptr->component_index]; v_expand = upsample->v_expand[compptr->component_index]; inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { for (v = v_expand; v > 0; v--) { inptr = input_data[inrow]; outptr = output_data[outrow++]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = GETJSAMPLE(*inptr++); for (h = h_expand; h > 0; h--) { *outptr++ = invalue; } } } inrow++; } } /* * Fast processing for the common case of 2:1 horizontal and 1:1 vertical. * It's still a box filter. */ METHODDEF void h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register JSAMPLE invalue; JSAMPROW outend; int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { inptr = input_data[inrow]; outptr = output_data[inrow]; outend = outptr + cinfo->output_width; while (outptr < outend) { invalue = GETJSAMPLE(*inptr++); *outptr++ = invalue; *outptr++ = invalue; } } } /* * Fast processing for the common case of 2:1 horizontal and 2:1 vertical. * It's still a box filter. */ METHODDEF void h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr1, outptr2; register JSAMPLE invalue; JSAMPROW outend; int inrow, outrow; inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { inptr = input_data[inrow++]; outptr1 = output_data[outrow++]; outptr2 = output_data[outrow++]; outend = outptr2 + cinfo->output_width; while (outptr2 < outend) { invalue = GETJSAMPLE(*inptr++); *outptr1++ = invalue; *outptr1++ = invalue; *outptr2++ = invalue; *outptr2++ = invalue; } } } /* * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical. * * The upsampling algorithm is linear interpolation between pixel centers, * also known as a "triangle filter". This is a good compromise between * speed and visual quality. The centers of the output pixels are 1/4 and 3/4 * of the way between input pixel centers. * * A note about the "bias" calculations: when rounding fractional values to * integer, we do not want to always round 0.5 up to the next integer. * If we did that, we'd introduce a noticeable bias towards larger values. * Instead, this code is arranged so that 0.5 will be rounded up or down at * alternate pixel locations (a simple ordered dither pattern). */ METHODDEF void h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr, outptr; register int invalue; register JDIMENSION colctr; int inrow; for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) { inptr = input_data[inrow]; outptr = output_data[inrow]; /* Special case for first column */ invalue = GETJSAMPLE(*inptr++); *outptr++ = (JSAMPLE) invalue; *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2); for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel */ invalue = GETJSAMPLE(*inptr++) * 3; *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2); *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2); } /* Special case for last column */ invalue = GETJSAMPLE(*inptr); *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2); *outptr++ = (JSAMPLE) invalue; } } /* * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical. * Again a triangle filter; see comments for h2v1 case, above. * * It is OK for us to reference the adjacent input rows because we demanded * context from the main buffer controller (see initialization code). */ METHODDEF void h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr) { JSAMPARRAY output_data = *output_data_ptr; register JSAMPROW inptr0, inptr1, outptr; #if BITS_IN_JSAMPLE == 8 register int thiscolsum, lastcolsum, nextcolsum; #else register INT32 thiscolsum, lastcolsum, nextcolsum; #endif register JDIMENSION colctr; int inrow, outrow, v; inrow = outrow = 0; while (outrow < cinfo->max_v_samp_factor) { for (v = 0; v < 2; v++) { /* inptr0 points to nearest input row, inptr1 points to next nearest */ inptr0 = input_data[inrow]; if (v == 0) /* next nearest is row above */ inptr1 = input_data[inrow-1]; else /* next nearest is row below */ inptr1 = input_data[inrow+1]; outptr = output_data[outrow++]; /* Special case for first column */ thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) { /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4); lastcolsum = thiscolsum; thiscolsum = nextcolsum; } /* Special case for last column */ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4); *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4); } inrow++; } } /* * Module initialization routine for upsampling. */ GLOBAL void jinit_upsampler (j_decompress_ptr cinfo) { my_upsample_ptr upsample; int ci; jpeg_component_info * compptr; boolean need_buffer, do_fancy; int h_in_group, v_in_group, h_out_group, v_out_group; upsample = (my_upsample_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_upsampler)); cinfo->upsample = (struct jpeg_upsampler *) upsample; upsample->pub.start_pass = start_pass; upsample->pub.upsample = sep_upsample; upsample->pub.need_context_rows = FALSE; /* until we find out differently */ if (cinfo->CCIR601_sampling) /* this isn't supported */ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); /* jdmainct.c doesn't support context rows when min_DCT_scaled_size = 1, * so don't ask for it. */ do_fancy = cinfo->do_fancy_upsampling && cinfo->min_DCT_scaled_size > 1; /* Verify we can handle the sampling factors, select per-component methods, * and create storage as needed. */ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; ci++, compptr++) { /* Compute size of an "input group" after IDCT scaling. This many samples * are to be converted to max_h_samp_factor * max_v_samp_factor pixels. */ h_in_group = (compptr->h_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; v_in_group = (compptr->v_samp_factor * compptr->DCT_scaled_size) / cinfo->min_DCT_scaled_size; h_out_group = cinfo->max_h_samp_factor; v_out_group = cinfo->max_v_samp_factor; upsample->rowgroup_height[ci] = v_in_group; /* save for use later */ need_buffer = TRUE; if (! compptr->component_needed) { /* Don't bother to upsample an uninteresting component. */ upsample->methods[ci] = noop_upsample; need_buffer = FALSE; } else if (h_in_group == h_out_group && v_in_group == v_out_group) { /* Fullsize components can be processed without any work. */ upsample->methods[ci] = fullsize_upsample; need_buffer = FALSE; } else if (h_in_group * 2 == h_out_group && v_in_group == v_out_group) { /* Special cases for 2h1v upsampling */ if (do_fancy && compptr->downsampled_width > 2) upsample->methods[ci] = h2v1_fancy_upsample; else upsample->methods[ci] = h2v1_upsample; } else if (h_in_group * 2 == h_out_group && v_in_group * 2 == v_out_group) { /* Special cases for 2h2v upsampling */ if (do_fancy && compptr->downsampled_width > 2) { upsample->methods[ci] = h2v2_fancy_upsample; upsample->pub.need_context_rows = TRUE; } else upsample->methods[ci] = h2v2_upsample; } else if ((h_out_group % h_in_group) == 0 && (v_out_group % v_in_group) == 0) { /* Generic integral-factors upsampling method */ upsample->methods[ci] = int_upsample; upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group); upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group); } else ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); if (need_buffer) { upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) jround_up((long) cinfo->output_width, (long) cinfo->max_h_samp_factor), (JDIMENSION) cinfo->max_v_samp_factor); } } } \ No newline at end of file diff --git a/Independent JPEG Group/jerror.c b/Independent JPEG Group/jerror.c new file mode 100644 index 0000000..10ae9ad --- /dev/null +++ b/Independent JPEG Group/jerror.c @@ -0,0 +1 @@ +/* * jerror.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains simple error-reporting and trace-message routines. * These are suitable for Unix-like systems and others where writing to * stderr is the right thing to do. Many applications will want to replace * some or all of these routines. * * These routines are used by both the compression and decompression code. */ /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ #include "jinclude.h" #include "jpeglib.h" #include "jversion.h" #include "jerror.h" /* get error codes */ #define JMAKE_MSG_TABLE #include "jerror.h" /* create message string table */ #ifndef EXIT_FAILURE /* define exit() codes if not provided */ #define EXIT_FAILURE 1 #endif /* * Error exit handler: must not return to caller. * * Applications may override this if they want to get control back after * an error. Typically one would longjmp somewhere instead of exiting. * The setjmp buffer can be made a private field within an expanded error * handler object. Note that the info needed to generate an error message * is stored in the error object, so you can generate the message now or * later, at your convenience. * You should make sure that the JPEG object is cleaned up (with jpeg_abort * or jpeg_destroy) at some point. */ METHODDEF void error_exit (j_common_ptr cinfo) { /* Always display the message */ (*cinfo->err->output_message) (cinfo); /* Let the memory manager delete any temp files before we die */ jpeg_destroy(cinfo); exit(EXIT_FAILURE); } /* * Actual output of an error or trace message. * Applications may override this method to send JPEG messages somewhere * other than stderr. */ METHODDEF void output_message (j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; /* Create the message */ (*cinfo->err->format_message) (cinfo, buffer); /* Send it to stderr, adding a newline */ fprintf(stderr, "%s\n", buffer); } /* * Decide whether to emit a trace or warning message. * msg_level is one of: * -1: recoverable corrupt-data warning, may want to abort. * 0: important advisory messages (always display to user). * 1: first level of tracing detail. * 2,3,...: successively more detailed tracing messages. * An application might override this method if it wanted to abort on warnings * or change the policy about which messages to display. */ METHODDEF void emit_message (j_common_ptr cinfo, int msg_level) { struct jpeg_error_mgr * err = cinfo->err; if (msg_level < 0) { /* It's a warning message. Since corrupt files may generate many warnings, * the policy implemented here is to show only the first warning, * unless trace_level >= 3. */ if (err->num_warnings == 0 || err->trace_level >= 3) (*err->output_message) (cinfo); /* Always count warnings in num_warnings. */ err->num_warnings++; } else { /* It's a trace message. Show it if trace_level >= msg_level. */ if (err->trace_level >= msg_level) (*err->output_message) (cinfo); } } /* * Format a message string for the most recent JPEG error or message. * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX * characters. Note that no '\n' character is added to the string. * Few applications should need to override this method. */ METHODDEF void format_message (j_common_ptr cinfo, char * buffer) { struct jpeg_error_mgr * err = cinfo->err; int msg_code = err->msg_code; const char * msgtext = NULL; const char * msgptr; char ch; boolean isstring; /* Look up message string in proper table */ if (msg_code > 0 && msg_code <= err->last_jpeg_message) { msgtext = err->jpeg_message_table[msg_code]; } else if (err->addon_message_table != NULL && msg_code >= err->first_addon_message && msg_code <= err->last_addon_message) { msgtext = err->addon_message_table[msg_code - err->first_addon_message]; } /* Defend against bogus message number */ if (msgtext == NULL) { err->msg_parm.i[0] = msg_code; msgtext = err->jpeg_message_table[0]; } /* Check for string parameter, as indicated by %s in the message text */ isstring = FALSE; msgptr = msgtext; while ((ch = *msgptr++) != '\0') { if (ch == '%') { if (*msgptr == 's') isstring = TRUE; break; } } /* Format the message into the passed buffer */ if (isstring) sprintf(buffer, msgtext, err->msg_parm.s); else sprintf(buffer, msgtext, err->msg_parm.i[0], err->msg_parm.i[1], err->msg_parm.i[2], err->msg_parm.i[3], err->msg_parm.i[4], err->msg_parm.i[5], err->msg_parm.i[6], err->msg_parm.i[7]); } /* * Reset error state variables at start of a new image. * This is called during compression startup to reset trace/error * processing to default state, without losing any application-specific * method pointers. An application might possibly want to override * this method if it has additional error processing state. */ METHODDEF void reset_error_mgr (j_common_ptr cinfo) { cinfo->err->num_warnings = 0; /* trace_level is not reset since it is an application-supplied parameter */ cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ } /* * Fill in the standard error-handling methods in a jpeg_error_mgr object. * Typical call is: * struct jpeg_compress_struct cinfo; * struct jpeg_error_mgr err; * * cinfo.err = jpeg_std_error(&err); * after which the application may override some of the methods. */ GLOBAL struct jpeg_error_mgr * jpeg_std_error (struct jpeg_error_mgr * err) { err->error_exit = error_exit; err->emit_message = emit_message; err->output_message = output_message; err->format_message = format_message; err->reset_error_mgr = reset_error_mgr; err->trace_level = 0; /* default = no tracing */ err->num_warnings = 0; /* no warnings emitted yet */ err->msg_code = 0; /* may be useful as a flag for "no error" */ /* Initialize message table pointers */ err->jpeg_message_table = jpeg_message_table; err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; err->addon_message_table = NULL; err->first_addon_message = 0; /* for safety */ err->last_addon_message = 0; return err; } \ No newline at end of file diff --git a/Independent JPEG Group/jerror.h b/Independent JPEG Group/jerror.h new file mode 100644 index 0000000..3ea6cda --- /dev/null +++ b/Independent JPEG Group/jerror.h @@ -0,0 +1 @@ +/* * jerror.h * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the error and message codes for the JPEG library. * Edit this file to add new codes, or to translate the message strings to * some other language. * A set of error-reporting macros are defined too. Some applications using * the JPEG library may wish to include this file to get the error codes * and/or the macros. */ /* To define the enum list of message codes, include this file without * defining JMAKE_MSG_TABLE. To create the message string table, include it * again with JMAKE_MSG_TABLE defined (this should be done in just one module). */ #ifdef JMAKE_MSG_TABLE const char * const jpeg_message_table[] = { #define JMESSAGE(code,string) string , #else /* not JMAKE_MSG_TABLE */ typedef enum { #define JMESSAGE(code,string) code , #endif /* JMAKE_MSG_TABLE */ JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */ /* For maintenance convenience, list is alphabetical by message code name */ JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, there are legal restrictions on arithmetic coding") JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK should be less than 64K") JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode") JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS") JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported") JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace") JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace") JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length") JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan") JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d") JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d") JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors") JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d") JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access") JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here") JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet") JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d") JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request") JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d") JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x") JMESSAGE(JERR_DHT_COUNTS, "Bogus DHT counts") JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d") JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d") JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)") JMESSAGE(JERR_EMS_READ, "Read from EMS failed") JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed") JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan") JMESSAGE(JERR_FILE_READ, "Input file read error") JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?") JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet") JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow") JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry") JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels") JMESSAGE(JERR_INPUT_EMPTY, "Empty input file") JMESSAGE(JERR_INPUT_EOF, "Premature end of input file") JMESSAGE(JERR_JFIF_MAJOR, "Unsupported JFIF revision number %d.%02d") JMESSAGE(JERR_NOTIMPL, "Not implemented yet") JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time") JMESSAGE(JERR_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG") JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported") JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined") JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image") JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined") JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x") JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)") JMESSAGE(JERR_PIPE_BUG, "Pipeline controller messed up") JMESSAGE(JERR_QUANT_COMPONENTS, "Cannot quantize more than %d color components") JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors") JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors") JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers") JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker") JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported SOF marker type 0x%02x") JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers") JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF") JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s") JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file") JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file") JMESSAGE(JERR_TFILE_WRITE, "Write failed on temporary file --- out of disk space?") JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up") JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation") JMESSAGE(JERR_XMS_READ, "Read from XMS failed") JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed") JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT) JMESSAGE(JMSG_VERSION, JVERSION) JMESSAGE(JTRC_16BIT_TABLES, "Caution: quantization tables are too coarse for baseline JPEG") JMESSAGE(JTRC_ADOBE, "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d") JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u") JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u") JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x") JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x") JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d") JMESSAGE(JTRC_DRI, "Define Restart Interval %u") JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u") JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u") JMESSAGE(JTRC_EOI, "End Of Image") JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d") JMESSAGE(JTRC_JFIF, "JFIF APP0 marker, density %dx%d %d") JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE, "Warning: thumbnail image size does not match data length %u") JMESSAGE(JTRC_JFIF_MINOR, "Warning: unknown JFIF revision number %d.%02d") JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image") JMESSAGE(JTRC_MISC_MARKER, "Skipping marker 0x%02x, length %u") JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x") JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u") JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors") JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors") JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization") JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d") JMESSAGE(JTRC_RST, "RST%d") JMESSAGE(JTRC_SMOOTH_NOTIMPL, "Smoothing not supported with nonstandard sampling ratios") JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d") JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d") JMESSAGE(JTRC_SOI, "Start of Image") JMESSAGE(JTRC_SOS, "Start Of Scan: %d components") JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d") JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s") JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s") JMESSAGE(JTRC_UNKNOWN_IDS, "Unrecognized component IDs %d %d %d, assuming YCbCr") JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u") JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u") JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d") JMESSAGE(JWRN_EXTRANEOUS_DATA, "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x") JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment") JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code") JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file") JMESSAGE(JWRN_MUST_RESYNC, "Corrupt JPEG data: found marker 0x%02x instead of RST%d") #ifdef JMAKE_MSG_TABLE NULL }; #else /* not JMAKE_MSG_TABLE */ JMSG_LASTMSGCODE } J_MESSAGE_CODE; #endif /* JMAKE_MSG_TABLE */ #undef JMESSAGE #ifndef JMAKE_MSG_TABLE /* Macros to simplify using the error and trace message stuff */ /* The first parameter is either type of cinfo pointer */ /* Fatal errors (print message and exit) */ #define ERREXIT(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT3(cinfo,code,p1,p2,p3) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (cinfo)->err->msg_parm.i[2] = (p3), \ (cinfo)->err->msg_parm.i[3] = (p4), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define ERREXITS(cinfo,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) #define MAKESTMT(stuff) do { stuff } while (0) /* Nonfatal errors (we can keep going, but the data is probably corrupt) */ #define WARNMS(cinfo,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS1(cinfo,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) #define WARNMS2(cinfo,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) /* Informational/debugging messages */ #define TRACEMS(cinfo,lvl,code) \ ((cinfo)->err->msg_code = (code), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS1(cinfo,lvl,code,p1) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS2(cinfo,lvl,code,p1,p2) \ ((cinfo)->err->msg_code = (code), \ (cinfo)->err->msg_parm.i[0] = (p1), \ (cinfo)->err->msg_parm.i[1] = (p2), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ (cinfo)->err->msg_code = (code); \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) #define TRACEMSS(cinfo,lvl,code,str) \ ((cinfo)->err->msg_code = (code), \ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) #endif /* JMAKE_MSG_TABLE */ \ No newline at end of file diff --git a/Independent JPEG Group/jfdctllm.c b/Independent JPEG Group/jfdctllm.c new file mode 100644 index 0000000..4c5af8e --- /dev/null +++ b/Independent JPEG Group/jfdctllm.c @@ -0,0 +1 @@ +/* * jfdctllm.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains a forward DCT (Discrete Cosine Transform) * transformation subroutine. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT * on each column. Direct algorithms are also available, but they are * much more complex and seem not to be any faster when reduced to code. * * The poop on this scaling stuff is as follows: * * Each 1-D DCT step produces outputs which are a factor of sqrt(N) * larger than the true DCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D DCT, * because the y0 and y4 outputs need not be divided by sqrt(N). * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (To scale up 12-bit sample data, an * intermediate INT32 array would be needed.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 25. Error analysis * shows that the values given below are the most effective. */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 0 /* lose a little precision to avoid overflow */ #endif #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) /* Convert a positive real constant to an integer scaled by CONST_SCALE. */ #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Descale and correctly round an INT32 value that's scaled by N bits. * We assume RIGHT_SHIFT rounds towards minus infinity, so adding * the fudge factor is correct for either sign of X. */ #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; * this provides a useful speedup on many machines. * There is no way to specify a 16x16->32 multiply in portable C, but * some C compilers will do the right thing if you provide the correct * combination of casts. * NB: for 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) #endif #ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const))) #endif #endif /* BITS_IN_JSAMPLE == 8 */ #ifndef MULTIPLY /* default definition */ #define MULTIPLY(var,const) ((var) * (const)) #endif /* * Perform the forward DCT on one block of samples. */ typedef int DCTELEM; GLOBAL void jpeg_fdct_llm (DCTELEM * data) { INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3, z4, z5; register DCTELEM *dataptr; int rowctr; SHIFT_TEMPS /* Pass 1: process rows. */ /* Note results are scaled up by sqrt(8) compared to a true DCT; */ /* furthermore, we scale the results by 2**PASS1_BITS. */ dataptr = data; for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { tmp0 = dataptr[0] + dataptr[7]; tmp7 = dataptr[0] - dataptr[7]; tmp1 = dataptr[1] + dataptr[6]; tmp6 = dataptr[1] - dataptr[6]; tmp2 = dataptr[2] + dataptr[5]; tmp5 = dataptr[2] - dataptr[5]; tmp3 = dataptr[3] + dataptr[4]; tmp4 = dataptr[3] - dataptr[4]; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS); dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS-PASS1_BITS); dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS-PASS1_BITS); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * cK represents cos(K*pi/16). * i0..i3 in the paper are tmp4..tmp7 here. */ z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS); dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS); dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS); dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS); dataptr += DCTSIZE; /* advance pointer to next row */ } /* Pass 2: process columns. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ dataptr = data; for (rowctr = DCTSIZE-1; rowctr >= 0; rowctr--) { tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; /* Even part per LL&M figure 1 --- note that published figure is faulty; * rotator "sqrt(2)*c1" should be "sqrt(2)*c6". */ tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+3); dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+3); z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100); dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865), CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065), CONST_BITS+PASS1_BITS+3); /* Odd part per figure 8 --- note paper omits factor of sqrt(2). * cK represents cos(K*pi/16). * i0..i3 in the paper are tmp4..tmp7 here. */ z1 = tmp4 + tmp7; z2 = tmp5 + tmp6; z3 = tmp4 + tmp6; z4 = tmp5 + tmp7; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS+PASS1_BITS+3); dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS+PASS1_BITS+3); dataptr++; /* advance pointer to next column */ } } \ No newline at end of file diff --git a/Independent JPEG Group/jidctllm.c b/Independent JPEG Group/jidctllm.c new file mode 100644 index 0000000..da4e461 --- /dev/null +++ b/Independent JPEG Group/jidctllm.c @@ -0,0 +1 @@ +/* * jidctllm.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains an inverse DCT (Discrete Cosine Transform) * transformation subroutine. * * This implementation is based on an algorithm described in * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics, * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991. * The primary algorithm described there uses 11 multiplies and 29 adds. * We use their alternate method with 12 multiplies and 32 adds. * The advantage of this method is that no data path contains more than one * multiplication; this allows a very simple and accurate implementation in * scaled fixed-point arithmetic, with a minimal number of shifts. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif /* * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT * on each row (or vice versa, but it's more convenient to emit a row at * a time). Direct algorithms are also available, but they are much more * complex and seem not to be any faster when reduced to code. * * The poop on this scaling stuff is as follows: * * Each 1-D IDCT step produces outputs which are a factor of sqrt(N) * larger than the true IDCT outputs. The final outputs are therefore * a factor of N larger than desired; since N=8 this can be cured by * a simple right shift at the end of the algorithm. The advantage of * this arrangement is that we save two multiplications per 1-D IDCT, * because the y0 and y4 inputs need not be divided by sqrt(N). * * We have to do addition and subtraction of the integer inputs, which * is no problem, and multiplication by fractional constants, which is * a problem to do in integer arithmetic. We multiply all the constants * by CONST_SCALE and convert them to integer constants (thus retaining * CONST_BITS bits of precision in the constants). After doing a * multiplication we have to divide the product by CONST_SCALE, with proper * rounding, to produce the correct output. This division can be done * cheaply as a right shift of CONST_BITS bits. We postpone shifting * as long as possible so that partial sums can be added together with * full fractional precision. * * The outputs of the first pass are scaled up by PASS1_BITS bits so that * they are represented to better-than-integral precision. These outputs * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word * with the recommended scaling. (To scale up 12-bit sample data further, an * intermediate INT32 array would be needed.) * * To avoid overflow of the 32-bit intermediate results in pass 2, we must * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis * shows that the values given below are the most effective. */ #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) /* Convert a positive real constant to an integer scaled by CONST_SCALE. */ #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */ #define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */ #define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */ #define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */ #define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */ #else #define FIX_0_298631336 FIX(0.298631336) #define FIX_0_390180644 FIX(0.390180644) #define FIX_0_541196100 FIX(0.541196100) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_175875602 FIX(1.175875602) #define FIX_1_501321110 FIX(1.501321110) #define FIX_1_847759065 FIX(1.847759065) #define FIX_1_961570560 FIX(1.961570560) #define FIX_2_053119869 FIX(2.053119869) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_072711026 FIX(3.072711026) #endif /* Descale and correctly round an INT32 value that's scaled by N bits. * We assume RIGHT_SHIFT rounds towards minus infinity, so adding * the fudge factor is correct for either sign of X. */ #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; * this provides a useful speedup on many machines. * There is no way to specify a 16x16->32 multiply in portable C, but * some C compilers will do the right thing if you provide the correct * combination of casts. * NB: for 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) #endif #ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const))) #endif #endif /* BITS_IN_JSAMPLE == 8 */ #ifndef MULTIPLY /* default definition */ #define MULTIPLY(var,const) ((var) * (const)) #endif /* * Perform the inverse DCT on one block of coefficients. */ GLOBAL void jpeg_idct_llm (j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp1, tmp2, tmp3; INT32 tmp10, tmp11, tmp12, tmp13; INT32 z1, z2, z3, z4, z5; JCOEFPTR inptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE2]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */ /* furthermore, we scale the results by 2**PASS1_BITS. */ inptr = coef_block; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { /* Due to quantization, we will usually find that many of the input * coefficients are zero, especially the AC terms. We can exploit this * by short-circuiting the IDCT calculation for any column in which all * the AC terms are zero. In that case each output is equal to the * DC coefficient (with scale factor as needed). * With typical images and quantization tables, half or more of the * column DCT calculations can be simplified this way. */ if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] | inptr[DCTSIZE*4] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] | inptr[DCTSIZE*7]) == 0) { /* AC terms all zero */ int dcval = ((int) inptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; wsptr[DCTSIZE*4] = dcval; wsptr[DCTSIZE*5] = dcval; wsptr[DCTSIZE*6] = dcval; wsptr[DCTSIZE*7] = dcval; inptr++; /* advance pointers to next column */ wsptr++; continue; } /* Even part: reverse the even part of the forward DCT. */ /* The rotator is sqrt(2)*c(-6). */ z2 = (INT32) inptr[DCTSIZE*2]; z3 = (INT32) inptr[DCTSIZE*6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); tmp0 = ((INT32) inptr[DCTSIZE*0] + (INT32) inptr[DCTSIZE*4]) << CONST_BITS; tmp1 = ((INT32) inptr[DCTSIZE*0] - (INT32) inptr[DCTSIZE*4]) << CONST_BITS; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) inptr[DCTSIZE*7]; tmp1 = (INT32) inptr[DCTSIZE*5]; tmp2 = (INT32) inptr[DCTSIZE*3]; tmp3 = (INT32) inptr[DCTSIZE*1]; z1 = tmp0 + tmp3; z2 = tmp1 + tmp2; z3 = tmp0 + tmp2; z4 = tmp1 + tmp3; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; tmp0 += z1 + z3; tmp1 += z2 + z4; tmp2 += z2 + z3; tmp3 += z1 + z4; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS); wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS); inptr++; /* advance pointers to next column */ wsptr++; } /* Pass 2: process rows from work array, store into output array. */ /* Note that we must descale the results by a factor of 8 == 2**3, */ /* and also undo the PASS1_BITS scaling. */ wsptr = workspace; for (ctr = 0; ctr < DCTSIZE; ctr++) { outptr = output_buf[ctr] + output_col; /* Rows of zeroes can be exploited in the same way as we did with columns. * However, the column calculation has created many nonzero AC terms, so * the simplification applies less often (typically 5% to 10% of the time). * On machines with very fast multiplication, it's possible that the * test takes more time than it's worth. In that case this section * may be commented out. */ #ifndef NO_ZERO_ROW_TEST if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[4] | wsptr[5] | wsptr[6] | wsptr[7]) == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; outptr[3] = dcval; outptr[4] = dcval; outptr[5] = dcval; outptr[6] = dcval; outptr[7] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part: reverse the even part of the forward DCT. */ /* The rotator is sqrt(2)*c(-6). */ z2 = (INT32) wsptr[2]; z3 = (INT32) wsptr[6]; z1 = MULTIPLY(z2 + z3, FIX_0_541196100); tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065); tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865); tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS; tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS; tmp10 = tmp0 + tmp3; tmp13 = tmp0 - tmp3; tmp11 = tmp1 + tmp2; tmp12 = tmp1 - tmp2; /* Odd part per figure 8; the matrix is unitary and hence its * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively. */ tmp0 = (INT32) wsptr[7]; tmp1 = (INT32) wsptr[5]; tmp2 = (INT32) wsptr[3]; tmp3 = (INT32) wsptr[1]; z1 = tmp0 + tmp3; z2 = tmp1 + tmp2; z3 = tmp0 + tmp2; z4 = tmp1 + tmp3; z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */ z3 += z5; z4 += z5; tmp0 += z1 + z3; tmp1 += z2 + z4; tmp2 += z2 + z3; tmp3 += z1 + z4; /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0, CONST_BITS+PASS1_BITS+3) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } \ No newline at end of file diff --git a/Independent JPEG Group/jidctred.c b/Independent JPEG Group/jidctred.c new file mode 100644 index 0000000..224b552 --- /dev/null +++ b/Independent JPEG Group/jidctred.c @@ -0,0 +1 @@ +/* * jidctred.c * * Copyright (C) 1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains inverse-DCT routines that produce high quality * reduced-size output: either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block. * * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M) * algorithm used in jidctllm.c. We simply replace each 8-to-8 1-D IDCT step * with an 8-to-4 step that produces the four averages of two adjacent outputs * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output). * These steps were derived by computing the corresponding values at the end * of the normal LL&M code, then simplifying as much as possible. * * 1x1 is trivial: just take the DC coefficient divided by 8. * * See jidctllm.c for additional comments. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jdct.h" /* Private declarations for DCT subsystem */ #ifdef IDCT_SCALING_SUPPORTED /* * This module is specialized to the case DCTSIZE = 8. */ #if DCTSIZE != 8 Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */ #endif #if BITS_IN_JSAMPLE == 8 #define CONST_BITS 13 #define PASS1_BITS 2 #else #define CONST_BITS 13 #define PASS1_BITS 1 /* lose a little precision to avoid overflow */ #endif #define ONE ((INT32) 1) #define CONST_SCALE (ONE << CONST_BITS) /* Convert a positive real constant to an integer scaled by CONST_SCALE. */ #define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5)) /* Some C compilers fail to reduce "FIX(constant)" at compile time, thus * causing a lot of useless floating-point operations at run time. * To get around this we use the following pre-calculated constants. * If you change CONST_BITS you may want to add appropriate values. * (With a reasonable C compiler, you can just rely on the FIX() macro...) */ #if CONST_BITS == 13 #define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */ #define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */ #define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */ #define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */ #define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */ #define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */ #define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */ #define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */ #define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */ #define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */ #define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */ #define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */ #define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */ #define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */ #else #define FIX_0_211164243 FIX(0.211164243) #define FIX_0_509795579 FIX(0.509795579) #define FIX_0_601344887 FIX(0.601344887) #define FIX_0_720959822 FIX(0.720959822) #define FIX_0_765366865 FIX(0.765366865) #define FIX_0_850430095 FIX(0.850430095) #define FIX_0_899976223 FIX(0.899976223) #define FIX_1_061594337 FIX(1.061594337) #define FIX_1_272758580 FIX(1.272758580) #define FIX_1_451774981 FIX(1.451774981) #define FIX_1_847759065 FIX(1.847759065) #define FIX_2_172734803 FIX(2.172734803) #define FIX_2_562915447 FIX(2.562915447) #define FIX_3_624509785 FIX(3.624509785) #endif /* Descale and correctly round an INT32 value that's scaled by N bits. * We assume RIGHT_SHIFT rounds towards minus infinity, so adding * the fudge factor is correct for either sign of X. */ #define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n) /* Multiply an INT32 variable by an INT32 constant to yield an INT32 result. * For 8-bit samples with the recommended scaling, all the variable * and constant values involved are no more than 16 bits wide, so a * 16x16->32 bit multiply can be used instead of a full 32x32 multiply; * this provides a useful speedup on many machines. * There is no way to specify a 16x16->32 multiply in portable C, but * some C compilers will do the right thing if you provide the correct * combination of casts. * NB: for 12-bit samples, a full 32-bit multiplication will be needed. */ #if BITS_IN_JSAMPLE == 8 #ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT16) (const))) #endif #ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */ #define MULTIPLY(var,const) (((INT16) (var)) * ((INT32) (const))) #endif #endif /* BITS_IN_JSAMPLE == 8 */ #ifndef MULTIPLY /* default definition */ #define MULTIPLY(var,const) ((var) * (const)) #endif /* * Perform the inverse DCT on one block of coefficients, * producing a reduced-size 4x4 output block. */ GLOBAL void jpeg_idct_4x4 (j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp2, tmp10, tmp12; INT32 z1, z2, z3, z4; JCOEFPTR inptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE*4]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*2] | inptr[DCTSIZE*3] | inptr[DCTSIZE*5] | inptr[DCTSIZE*6] | inptr[DCTSIZE*7]) == 0) { /* AC terms all zero; we need not examine term 4 for 4x4 output */ int dcval = ((int) inptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; wsptr[DCTSIZE*2] = dcval; wsptr[DCTSIZE*3] = dcval; inptr++; /* advance pointers to next column */ wsptr++; continue; } /* Even part */ tmp0 = ((INT32) inptr[DCTSIZE*0]) << (CONST_BITS+1); tmp2 = MULTIPLY((INT32) inptr[DCTSIZE*2], FIX_1_847759065) + MULTIPLY((INT32) inptr[DCTSIZE*6], - FIX_0_765366865); tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; /* Odd part */ z1 = (INT32) inptr[DCTSIZE*7]; z2 = (INT32) inptr[DCTSIZE*5]; z3 = (INT32) inptr[DCTSIZE*3]; z4 = (INT32) inptr[DCTSIZE*1]; tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ /* Final output stage */ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1); wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1); wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1); wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1); inptr++; /* advance pointers to next column */ wsptr++; } /* Pass 2: process 4 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 4; ctr++) { outptr = output_buf[ctr] + output_col; /* It's not clear whether a zero row test is worthwhile here ... */ #ifndef NO_ZERO_ROW_TEST if ((wsptr[1] | wsptr[2] | wsptr[3] | wsptr[5] | wsptr[6] | wsptr[7]) == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; outptr[2] = dcval; outptr[3] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part */ tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1); tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065) + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865); tmp10 = tmp0 + tmp2; tmp12 = tmp0 - tmp2; /* Odd part */ z1 = (INT32) wsptr[7]; z2 = (INT32) wsptr[5]; z3 = (INT32) wsptr[3]; z4 = (INT32) wsptr[1]; tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */ /* Final output stage */ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0, CONST_BITS+PASS1_BITS+3+1) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } /* * Perform the inverse DCT on one block of coefficients, * producing a reduced-size 2x2 output block. */ GLOBAL void jpeg_idct_2x2 (j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { INT32 tmp0, tmp10; JCOEFPTR inptr; int * wsptr; JSAMPROW outptr; JSAMPLE *range_limit = IDCT_range_limit(cinfo); int ctr; int workspace[DCTSIZE*2]; /* buffers data between passes */ SHIFT_TEMPS /* Pass 1: process columns from input, store into work array. */ inptr = coef_block; wsptr = workspace; for (ctr = DCTSIZE; ctr > 0; ctr--) { if ((inptr[DCTSIZE*1] | inptr[DCTSIZE*3] | inptr[DCTSIZE*5] | inptr[DCTSIZE*7]) == 0) { /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */ int dcval = ((int) inptr[DCTSIZE*0]) << PASS1_BITS; wsptr[DCTSIZE*0] = dcval; wsptr[DCTSIZE*1] = dcval; inptr++; /* advance pointers to next column */ wsptr++; continue; } /* Even part */ tmp10 = ((INT32) inptr[DCTSIZE*0]) << (CONST_BITS+2); /* Odd part */ tmp0 = MULTIPLY((INT32) inptr[DCTSIZE*7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + MULTIPLY((INT32) inptr[DCTSIZE*5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + MULTIPLY((INT32) inptr[DCTSIZE*3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + MULTIPLY((INT32) inptr[DCTSIZE*1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ /* Final output stage */ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2); wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2); inptr++; /* advance pointers to next column */ wsptr++; } /* Pass 2: process 2 rows from work array, store into output array. */ wsptr = workspace; for (ctr = 0; ctr < 2; ctr++) { outptr = output_buf[ctr] + output_col; /* It's not clear whether a zero row test is worthwhile here ... */ #ifndef NO_ZERO_ROW_TEST if ((wsptr[1] | wsptr[3] | wsptr[5] | wsptr[7]) == 0) { /* AC terms all zero */ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3) & RANGE_MASK]; outptr[0] = dcval; outptr[1] = dcval; wsptr += DCTSIZE; /* advance pointer to next row */ continue; } #endif /* Even part */ tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2); /* Odd part */ tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */ + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */ + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */ + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */ /* Final output stage */ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0, CONST_BITS+PASS1_BITS+3+2) & RANGE_MASK]; outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0, CONST_BITS+PASS1_BITS+3+2) & RANGE_MASK]; wsptr += DCTSIZE; /* advance pointer to next row */ } } /* * Perform the inverse DCT on one block of coefficients, * producing a reduced-size 1x1 output block. */ GLOBAL void jpeg_idct_1x1 (j_decompress_ptr cinfo, JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col) { int dcval; JSAMPLE *range_limit = IDCT_range_limit(cinfo); SHIFT_TEMPS /* We hardly need an inverse DCT routine for this: just take the * average pixel value, which is one-eighth of the DC coefficient. */ dcval = (int) RIGHT_SHIFT((INT32) coef_block[0] + 4, 3); output_buf[0][output_col] = range_limit[dcval & RANGE_MASK]; } #endif /* IDCT_SCALING_SUPPORTED */ \ No newline at end of file diff --git a/Independent JPEG Group/jinclude.h b/Independent JPEG Group/jinclude.h new file mode 100644 index 0000000..154e69c --- /dev/null +++ b/Independent JPEG Group/jinclude.h @@ -0,0 +1 @@ +/* * jinclude.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file exists to provide a single place to fix any problems with * including the wrong system include files. (Common problems are taken * care of by the standard jconfig symbols, but on really weird systems * you may have to edit this file.) * * NOTE: this file is NOT intended to be included by applications using the * JPEG library. Most applications need only include jpeglib.h. */ /* Include auto-config file to find out which system include files we need. */ #include "jconfig.h" /* auto configuration options */ #define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ /* * We need the NULL macro and size_t typedef. * On an ANSI-conforming system it is sufficient to include . * Otherwise, we get them from or ; we may have to * pull in as well. * Note that the core JPEG library does not require ; * only the default error handler and data source/destination modules do. * But we must pull it in because of the references to FILE in jpeglib.h. * You can remove those references if you want to compile without . */ #ifdef HAVE_STDDEF_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef NEED_SYS_TYPES_H #include #endif #include /* * We need memory copying and zeroing functions, plus strncpy(). * ANSI and System V implementations declare these in . * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). * Some systems may declare memset and memcpy in . * * NOTE: we assume the size parameters to these functions are of type size_t. * Change the casts in these macros if not! */ #ifdef NEED_BSD_STRINGS #include #define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) #define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) #else /* not BSD, assume ANSI/SysV string lib */ #include #define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) #define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) #endif /* * In ANSI C, and indeed any rational implementation, size_t is also the * type returned by sizeof(). However, it seems there are some irrational * implementations out there, in which sizeof() returns an int even though * size_t is defined as long or unsigned long. To ensure consistent results * we always use this SIZEOF() macro in place of using sizeof() directly. */ #define SIZEOF(object) ((size_t) sizeof(object)) /* * The modules that use fread() and fwrite() always invoke them through * these macros. On some systems you may need to twiddle the argument casts. * CAUTION: argument order is different from underlying functions! */ #define JFREAD(file,buf,sizeofbuf) \ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) #define JFWRITE(file,buf,sizeofbuf) \ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) \ No newline at end of file diff --git a/Independent JPEG Group/jmemansi.c b/Independent JPEG Group/jmemansi.c new file mode 100644 index 0000000..e5051e7 --- /dev/null +++ b/Independent JPEG Group/jmemansi.c @@ -0,0 +1 @@ +/* * jmemansi.c * * Copyright (C) 1992-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a simple generic implementation of the system- * dependent portion of the JPEG memory manager. This implementation * assumes that you have the ANSI-standard library routine tmpfile(). * Also, the problem of determining the amount of memory available * is shoved onto the user. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); #endif #ifndef SEEK_SET /* pre-ANSI systems may not define this; */ #define SEEK_SET 0 /* if not, assume 0 is correct */ #endif /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL void jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) { free(object); } /* * "Large" objects are treated the same as "small" ones. * NB: although we include FAR keywords in the routine declarations, * this file won't actually work in 80x86 small model. */ GLOBAL void FAR * jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) { return (void FAR *) malloc(sizeofobject); } GLOBAL void jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) { free(object); } /* * This routine computes the total memory space available for allocation. * It's impossible to do this in a portable way; our current solution is * to make the user tell us (with a default value set at compile time). * If you can actually get the available space, it's a good idea to subtract * a slop factor of 5% or so. */ #ifndef DEFAULT_MAX_MEM /* so can override from makefile */ #define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ #endif GLOBAL long jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated) { return cinfo->mem->max_memory_to_use - already_allocated; } /* * Backing store (temporary file) management. * Backing store objects are only used when the value returned by * jpeg_mem_available is less than the total space needed. You can dispense * with these routines if you have plenty of virtual memory; see jmemnobs.c. */ METHODDEF void read_backing_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(cinfo, JERR_TFILE_SEEK); if (JFREAD(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(cinfo, JERR_TFILE_READ); } METHODDEF void write_backing_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(cinfo, JERR_TFILE_SEEK); if (JFWRITE(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(cinfo, JERR_TFILE_WRITE); } METHODDEF void close_backing_store (j_common_ptr cinfo, backing_store_ptr info) { fclose(info->temp_file); /* Since this implementation uses tmpfile() to create the file, * no explicit file deletion is needed. */ } /* * Initial opening of a backing-store object. * * This version uses tmpfile(), which constructs a suitable file name * behind the scenes. We don't have to use info->temp_name[] at all; * indeed, we can't even find out the actual name of the temp file. */ GLOBAL void jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { if ((info->temp_file = tmpfile()) == NULL) ERREXITS(cinfo, JERR_TFILE_CREATE, ""); info->read_backing_store = read_backing_store; info->write_backing_store = write_backing_store; info->close_backing_store = close_backing_store; } /* * These routines take care of any system-dependent initialization and * cleanup required. */ GLOBAL long jpeg_mem_init (j_common_ptr cinfo) { return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ } GLOBAL void jpeg_mem_term (j_common_ptr cinfo) { /* no work */ } \ No newline at end of file diff --git a/Independent JPEG Group/jmemdos.c b/Independent JPEG Group/jmemdos.c new file mode 100644 index 0000000..74ac19c --- /dev/null +++ b/Independent JPEG Group/jmemdos.c @@ -0,0 +1 @@ +/* * jmemdos.c * * Copyright (C) 1992-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides an MS-DOS-compatible implementation of the system- * dependent portion of the JPEG memory manager. Temporary data can be * stored in extended or expanded memory as well as in regular DOS files. * * If you use this file, you must be sure that NEED_FAR_POINTERS is defined * if you compile in a small-data memory model; it should NOT be defined if * you use a large-data memory model. This file is not recommended if you * are using a flat-memory-space 386 environment such as DJGCC or Watcom C. * Also, this code will NOT work if struct fields are aligned on greater than * 2-byte boundaries. * * Based on code contributed by Ge' Weijers. */ /* * If you have both extended and expanded memory, you may want to change the * order in which they are tried in jopen_backing_store. On a 286 machine * expanded memory is usually faster, since extended memory access involves * an expensive protected-mode-and-back switch. On 386 and better, extended * memory is usually faster. As distributed, the code tries extended memory * first (what? not everyone has a 386? :-). * * You can disable use of extended/expanded memory entirely by altering these * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0). */ #ifndef XMS_SUPPORTED #define XMS_SUPPORTED 1 #endif #ifndef EMS_SUPPORTED #define EMS_SUPPORTED 1 #endif #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef HAVE_STDLIB_H /* should declare these */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); extern char * getenv JPP((const char * name)); #endif #ifdef NEED_FAR_POINTERS #ifdef __TURBOC__ /* These definitions work for Borland C (Turbo C) */ #include /* need farmalloc(), farfree() */ #define far_malloc(x) farmalloc(x) #define far_free(x) farfree(x) #else /* These definitions work for Microsoft C and compatible compilers */ #include /* need _fmalloc(), _ffree() */ #define far_malloc(x) _fmalloc(x) #define far_free(x) _ffree(x) #endif #else /* not NEED_FAR_POINTERS */ #define far_malloc(x) malloc(x) #define far_free(x) free(x) #endif /* NEED_FAR_POINTERS */ #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #else #define READ_BINARY "rb" #endif #if MAX_ALLOC_CHUNK >= 65535L /* make sure jconfig.h got this right */ MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */ #endif /* * Declarations for assembly-language support routines (see jmemdosa.asm). * * The functions are declared "far" as are all pointer arguments; * this ensures the assembly source code will work regardless of the * compiler memory model. We assume "short" is 16 bits, "long" is 32. */ typedef void far * XMSDRIVER; /* actually a pointer to code */ typedef struct { /* registers for calling XMS driver */ unsigned short ax, dx, bx; void far * ds_si; } XMScontext; typedef struct { /* registers for calling EMS driver */ unsigned short ax, dx, bx; void far * ds_si; } EMScontext; EXTERN short far jdos_open JPP((short far * handle, char far * filename)); EXTERN short far jdos_close JPP((short handle)); EXTERN short far jdos_seek JPP((short handle, long offset)); EXTERN short far jdos_read JPP((short handle, void far * buffer, unsigned short count)); EXTERN short far jdos_write JPP((short handle, void far * buffer, unsigned short count)); EXTERN void far jxms_getdriver JPP((XMSDRIVER far *)); EXTERN void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *)); EXTERN short far jems_available JPP((void)); EXTERN void far jems_calldriver JPP((EMScontext far *)); /* * Selection of a file name for a temporary file. * This is highly system-dependent, and you may want to customize it. */ static int next_file_num; /* to distinguish among several temp files */ LOCAL void select_file_name (char * fname) { const char * env; char * ptr; FILE * tfile; /* Keep generating file names till we find one that's not in use */ for (;;) { /* Get temp directory name from environment TMP or TEMP variable; * if none, use "." */ if ((env = (const char *) getenv("TMP")) == NULL) if ((env = (const char *) getenv("TEMP")) == NULL) env = "."; if (*env == '\0') /* null string means "." */ env = "."; ptr = fname; /* copy name to fname */ while (*env != '\0') *ptr++ = *env++; if (ptr[-1] != '\\' && ptr[-1] != '/') *ptr++ = '\\'; /* append backslash if not in env variable */ /* Append a suitable file name */ next_file_num++; /* advance counter */ sprintf(ptr, "JPG%03d.TMP", next_file_num); /* Probe to see if file name is already in use */ if ((tfile = fopen(fname, READ_BINARY)) == NULL) break; fclose(tfile); /* oops, it's there; close tfile & try again */ } } /* * Near-memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL void jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) { free(object); } /* * "Large" objects are allocated in far memory, if possible */ GLOBAL void FAR * jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) { return (void FAR *) far_malloc(sizeofobject); } GLOBAL void jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) { far_free(object); } /* * This routine computes the total memory space available for allocation. * It's impossible to do this in a portable way; our current solution is * to make the user tell us (with a default value set at compile time). * If you can actually get the available space, it's a good idea to subtract * a slop factor of 5% or so. */ #ifndef DEFAULT_MAX_MEM /* so can override from makefile */ #define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */ #endif GLOBAL long jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated) { return cinfo->mem->max_memory_to_use - already_allocated; } /* * Backing store (temporary file) management. * Backing store objects are only used when the value returned by * jpeg_mem_available is less than the total space needed. You can dispense * with these routines if you have plenty of virtual memory; see jmemnobs.c. */ /* * For MS-DOS we support three types of backing storage: * 1. Conventional DOS files. We access these by direct DOS calls rather * than via the stdio package. This provides a bit better performance, * but the real reason is that the buffers to be read or written are FAR. * The stdio library for small-data memory models can't cope with that. * 2. Extended memory, accessed per the XMS V2.0 specification. * 3. Expanded memory, accessed per the LIM/EMS 4.0 specification. * You'll need copies of those specs to make sense of the related code. * The specs are available by Internet FTP from the SIMTEL archives * (oak.oakland.edu and its various mirror sites). See files * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip. */ /* * Access methods for a DOS file. */ METHODDEF void read_file_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (jdos_seek(info->handle.file_handle, file_offset)) ERREXIT(cinfo, JERR_TFILE_SEEK); /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ if (byte_count > 65535L) /* safety check */ ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); if (jdos_read(info->handle.file_handle, buffer_address, (unsigned short) byte_count)) ERREXIT(cinfo, JERR_TFILE_READ); } METHODDEF void write_file_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (jdos_seek(info->handle.file_handle, file_offset)) ERREXIT(cinfo, JERR_TFILE_SEEK); /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */ if (byte_count > 65535L) /* safety check */ ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK); if (jdos_write(info->handle.file_handle, buffer_address, (unsigned short) byte_count)) ERREXIT(cinfo, JERR_TFILE_WRITE); } METHODDEF void close_file_store (j_common_ptr cinfo, backing_store_ptr info) { jdos_close(info->handle.file_handle); /* close the file */ remove(info->temp_name); /* delete the file */ /* If your system doesn't have remove(), try unlink() instead. * remove() is the ANSI-standard name for this function, but * unlink() was more common in pre-ANSI systems. */ TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name); } LOCAL boolean open_file_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { short handle; select_file_name(info->temp_name); if (jdos_open((short far *) & handle, (char far *) info->temp_name)) { /* might as well exit since jpeg_open_backing_store will fail anyway */ ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); return FALSE; } info->handle.file_handle = handle; info->read_backing_store = read_file_store; info->write_backing_store = write_file_store; info->close_backing_store = close_file_store; TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); return TRUE; /* succeeded */ } /* * Access methods for extended memory. */ #if XMS_SUPPORTED static XMSDRIVER xms_driver; /* saved address of XMS driver */ typedef union { /* either long offset or real-mode pointer */ long offset; void far * ptr; } XMSPTR; typedef struct { /* XMS move specification structure */ long length; XMSH src_handle; XMSPTR src; XMSH dst_handle; XMSPTR dst; } XMSspec; #define ODD(X) (((X) & 1L) != 0) METHODDEF void read_xms_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { XMScontext ctx; XMSspec spec; char endbuffer[2]; /* The XMS driver can't cope with an odd length, so handle the last byte * specially if byte_count is odd. We don't expect this to be common. */ spec.length = byte_count & (~ 1L); spec.src_handle = info->handle.xms_handle; spec.src.offset = file_offset; spec.dst_handle = 0; spec.dst.ptr = buffer_address; ctx.ds_si = (void far *) & spec; ctx.ax = 0x0b00; /* EMB move */ jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax != 1) ERREXIT(cinfo, JERR_XMS_READ); if (ODD(byte_count)) { read_xms_store(cinfo, info, (void FAR *) endbuffer, file_offset + byte_count - 1L, 2L); ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0]; } } METHODDEF void write_xms_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { XMScontext ctx; XMSspec spec; char endbuffer[2]; /* The XMS driver can't cope with an odd length, so handle the last byte * specially if byte_count is odd. We don't expect this to be common. */ spec.length = byte_count & (~ 1L); spec.src_handle = 0; spec.src.ptr = buffer_address; spec.dst_handle = info->handle.xms_handle; spec.dst.offset = file_offset; ctx.ds_si = (void far *) & spec; ctx.ax = 0x0b00; /* EMB move */ jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax != 1) ERREXIT(cinfo, JERR_XMS_WRITE); if (ODD(byte_count)) { read_xms_store(cinfo, info, (void FAR *) endbuffer, file_offset + byte_count - 1L, 2L); endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L]; write_xms_store(cinfo, info, (void FAR *) endbuffer, file_offset + byte_count - 1L, 2L); } } METHODDEF void close_xms_store (j_common_ptr cinfo, backing_store_ptr info) { XMScontext ctx; ctx.dx = info->handle.xms_handle; ctx.ax = 0x0a00; jxms_calldriver(xms_driver, (XMScontext far *) & ctx); TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle); /* we ignore any error return from the driver */ } LOCAL boolean open_xms_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { XMScontext ctx; /* Get address of XMS driver */ jxms_getdriver((XMSDRIVER far *) & xms_driver); if (xms_driver == NULL) return FALSE; /* no driver to be had */ /* Get version number, must be >= 2.00 */ ctx.ax = 0x0000; jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax < (unsigned short) 0x0200) return FALSE; /* Try to get space (expressed in kilobytes) */ ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10); ctx.ax = 0x0900; jxms_calldriver(xms_driver, (XMScontext far *) & ctx); if (ctx.ax != 1) return FALSE; /* Succeeded, save the handle and away we go */ info->handle.xms_handle = ctx.dx; info->read_backing_store = read_xms_store; info->write_backing_store = write_xms_store; info->close_backing_store = close_xms_store; TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx); return TRUE; /* succeeded */ } #endif /* XMS_SUPPORTED */ /* * Access methods for expanded memory. */ #if EMS_SUPPORTED /* The EMS move specification structure requires word and long fields aligned * at odd byte boundaries. Some compilers will align struct fields at even * byte boundaries. While it's usually possible to force byte alignment, * that causes an overall performance penalty and may pose problems in merging * JPEG into a larger application. Instead we accept some rather dirty code * here. Note this code would fail if the hardware did not allow odd-byte * word & long accesses, but all 80x86 CPUs do. */ typedef void far * EMSPTR; typedef union { /* EMS move specification structure */ long length; /* It's easy to access first 4 bytes */ char bytes[18]; /* Misaligned fields in here! */ } EMSspec; /* Macros for accessing misaligned fields */ #define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset]))) #define SRC_TYPE(spec) FIELD_AT(spec,4,char) #define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH) #define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short) #define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short) #define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR) #define DST_TYPE(spec) FIELD_AT(spec,11,char) #define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH) #define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short) #define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short) #define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR) #define EMSPAGESIZE 16384L /* gospel, see the EMS specs */ #define HIBYTE(W) (((W) >> 8) & 0xFF) #define LOBYTE(W) ((W) & 0xFF) METHODDEF void read_ems_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { EMScontext ctx; EMSspec spec; spec.length = byte_count; SRC_TYPE(spec) = 1; SRC_HANDLE(spec) = info->handle.ems_handle; SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); DST_TYPE(spec) = 0; DST_HANDLE(spec) = 0; DST_PTR(spec) = buffer_address; ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) ERREXIT(cinfo, JERR_EMS_READ); } METHODDEF void write_ems_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { EMScontext ctx; EMSspec spec; spec.length = byte_count; SRC_TYPE(spec) = 0; SRC_HANDLE(spec) = 0; SRC_PTR(spec) = buffer_address; DST_TYPE(spec) = 1; DST_HANDLE(spec) = info->handle.ems_handle; DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE); DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE); ctx.ds_si = (void far *) & spec; ctx.ax = 0x5700; /* move memory region */ jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) ERREXIT(cinfo, JERR_EMS_WRITE); } METHODDEF void close_ems_store (j_common_ptr cinfo, backing_store_ptr info) { EMScontext ctx; ctx.ax = 0x4500; ctx.dx = info->handle.ems_handle; jems_calldriver((EMScontext far *) & ctx); TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle); /* we ignore any error return from the driver */ } LOCAL boolean open_ems_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { EMScontext ctx; /* Is EMS driver there? */ if (! jems_available()) return FALSE; /* Get status, make sure EMS is OK */ ctx.ax = 0x4000; jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) return FALSE; /* Get version, must be >= 4.0 */ ctx.ax = 0x4600; jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40) return FALSE; /* Try to allocate requested space */ ctx.ax = 0x4300; ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE); jems_calldriver((EMScontext far *) & ctx); if (HIBYTE(ctx.ax) != 0) return FALSE; /* Succeeded, save the handle and away we go */ info->handle.ems_handle = ctx.dx; info->read_backing_store = read_ems_store; info->write_backing_store = write_ems_store; info->close_backing_store = close_ems_store; TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx); return TRUE; /* succeeded */ } #endif /* EMS_SUPPORTED */ /* * Initial opening of a backing-store object. */ GLOBAL void jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { /* Try extended memory, then expanded memory, then regular file. */ #if XMS_SUPPORTED if (open_xms_store(cinfo, info, total_bytes_needed)) return; #endif #if EMS_SUPPORTED if (open_ems_store(cinfo, info, total_bytes_needed)) return; #endif if (open_file_store(cinfo, info, total_bytes_needed)) return; ERREXITS(cinfo, JERR_TFILE_CREATE, ""); } /* * These routines take care of any system-dependent initialization and * cleanup required. */ GLOBAL long jpeg_mem_init (j_common_ptr cinfo) { next_file_num = 0; /* initialize temp file name generator */ return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ } GLOBAL void jpeg_mem_term (j_common_ptr cinfo) { /* Microsoft C, at least in v6.00A, will not successfully reclaim freed * blocks of size > 32Kbytes unless we give it a kick in the rear, like so: */ #ifdef NEED_FHEAPMIN _fheapmin(); #endif } \ No newline at end of file diff --git a/Independent JPEG Group/jmemdosa.asm b/Independent JPEG Group/jmemdosa.asm new file mode 100644 index 0000000..80a3237 --- /dev/null +++ b/Independent JPEG Group/jmemdosa.asm @@ -0,0 +1 @@ +; ; jmemdosa.asm ; ; Copyright (C) 1992, Thomas G. Lane. ; This file is part of the Independent JPEG Group's software. ; For conditions of distribution and use, see the accompanying README file. ; ; This file contains low-level interface routines to support the MS-DOS ; backing store manager (jmemdos.c). Routines are provided to access disk ; files through direct DOS calls, and to access XMS and EMS drivers. ; ; This file should assemble with Microsoft's MASM or any compatible ; assembler (including Borland's Turbo Assembler). If you haven't got ; a compatible assembler, better fall back to jmemansi.c or jmemname.c. ; ; To minimize dependence on the C compiler's register usage conventions, ; we save and restore all 8086 registers, even though most compilers only ; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return ; values, which everybody returns in AX. ; ; Based on code contributed by Ge' Weijers. ; JMEMDOSA_TXT segment byte public 'CODE' assume cs:JMEMDOSA_TXT public _jdos_open public _jdos_close public _jdos_seek public _jdos_read public _jdos_write public _jxms_getdriver public _jxms_calldriver public _jems_available public _jems_calldriver ; ; short far jdos_open (short far * handle, char far * filename) ; ; Create and open a temporary file ; _jdos_open proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov cx,0 ; normal file attributes lds dx,dword ptr [bp+10] ; get filename pointer mov ah,3ch ; create file int 21h jc open_err ; if failed, return error code lds bx,dword ptr [bp+6] ; get handle pointer mov word ptr [bx],ax ; save the handle xor ax,ax ; return zero for OK open_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_open endp ; ; short far jdos_close (short handle) ; ; Close the file handle ; _jdos_close proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle mov ah,3eh ; close file int 21h jc close_err ; if failed, return error code xor ax,ax ; return zero for OK close_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_close endp ; ; short far jdos_seek (short handle, long offset) ; ; Set file position ; _jdos_seek proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle mov dx,word ptr [bp+8] ; LS offset mov cx,word ptr [bp+10] ; MS offset mov ax,4200h ; absolute seek int 21h jc seek_err ; if failed, return error code xor ax,ax ; return zero for OK seek_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_seek endp ; ; short far jdos_read (short handle, void far * buffer, unsigned short count) ; ; Read from file ; _jdos_read proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle lds dx,dword ptr [bp+8] ; buffer address mov cx,word ptr [bp+12] ; number of bytes mov ah,3fh ; read file int 21h jc read_err ; if failed, return error code cmp ax,word ptr [bp+12] ; make sure all bytes were read je read_ok mov ax,1 ; else return 1 for not OK jmp short read_err read_ok: xor ax,ax ; return zero for OK read_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_read endp ; ; short far jdos_write (short handle, void far * buffer, unsigned short count) ; ; Write to file ; _jdos_write proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov bx,word ptr [bp+6] ; file handle lds dx,dword ptr [bp+8] ; buffer address mov cx,word ptr [bp+12] ; number of bytes mov ah,40h ; write file int 21h jc write_err ; if failed, return error code cmp ax,word ptr [bp+12] ; make sure all bytes written je write_ok mov ax,1 ; else return 1 for not OK jmp short write_err write_ok: xor ax,ax ; return zero for OK write_err: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jdos_write endp ; ; void far jxms_getdriver (XMSDRIVER far *) ; ; Get the address of the XMS driver, or NULL if not available ; _jxms_getdriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds mov ax,4300h ; call multiplex interrupt with int 2fh ; a magic cookie, hex 4300 cmp al,80h ; AL should contain hex 80 je xmsavail xor dx,dx ; no XMS driver available xor ax,ax ; return a nil pointer jmp short xmsavail_done xmsavail: mov ax,4310h ; fetch driver address with int 2fh ; another magic cookie mov dx,es ; copy address to dx:ax mov ax,bx xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value mov word ptr es:[bx],ax mov word ptr es:[bx+2],dx pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jxms_getdriver endp ; ; void far jxms_calldriver (XMSDRIVER, XMScontext far *) ; ; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers. ; These are loaded, the XMS call is performed, and the new values of the ; AX,DX,BX registers are written back to the context structure. ; _jxms_calldriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds les bx,dword ptr [bp+10] ; get XMScontext pointer mov ax,word ptr es:[bx] ; load registers mov dx,word ptr es:[bx+2] mov si,word ptr es:[bx+6] mov ds,word ptr es:[bx+8] mov bx,word ptr es:[bx+4] call dword ptr [bp+6] ; call the driver mov cx,bx ; save returned BX for a sec les bx,dword ptr [bp+10] ; get XMScontext pointer mov word ptr es:[bx],ax ; put back ax,dx,bx mov word ptr es:[bx+2],dx mov word ptr es:[bx+4],cx pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jxms_calldriver endp ; ; short far jems_available (void) ; ; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs) ; _jems_available proc far push si ; save all registers for safety push di push bx push cx push dx push es push ds mov ax,3567h ; get interrupt vector 67h int 21h push cs pop ds mov di,000ah ; check offs 10 in returned seg lea si,ASCII_device_name ; against literal string mov cx,8 cld repe cmpsb jne no_ems mov ax,1 ; match, it's there jmp short avail_done no_ems: xor ax,ax ; it's not there avail_done: pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si ret ASCII_device_name db "EMMXXXX0" _jems_available endp ; ; void far jems_calldriver (EMScontext far *) ; ; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers. ; These are loaded, the EMS trap is performed, and the new values of the ; AX,DX,BX registers are written back to the context structure. ; _jems_calldriver proc far push bp ; linkage mov bp,sp push si ; save all registers for safety push di push bx push cx push dx push es push ds les bx,dword ptr [bp+6] ; get EMScontext pointer mov ax,word ptr es:[bx] ; load registers mov dx,word ptr es:[bx+2] mov si,word ptr es:[bx+6] mov ds,word ptr es:[bx+8] mov bx,word ptr es:[bx+4] int 67h ; call the EMS driver mov cx,bx ; save returned BX for a sec les bx,dword ptr [bp+6] ; get EMScontext pointer mov word ptr es:[bx],ax ; put back ax,dx,bx mov word ptr es:[bx+2],dx mov word ptr es:[bx+4],cx pop ds ; restore registers and exit pop es pop dx pop cx pop bx pop di pop si pop bp ret _jems_calldriver endp JMEMDOSA_TXT ends end \ No newline at end of file diff --git a/Independent JPEG Group/jmemmgr.c b/Independent JPEG Group/jmemmgr.c new file mode 100644 index 0000000..71c5829 --- /dev/null +++ b/Independent JPEG Group/jmemmgr.c @@ -0,0 +1 @@ +/* * jmemmgr.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains the JPEG system-independent memory management * routines. This code is usable across a wide variety of machines; most * of the system dependencies have been isolated in a separate file. * The major functions provided here are: * * pool-based allocation and freeing of memory; * * policy decisions about how to divide available memory among the * virtual arrays; * * control logic for swapping virtual arrays between main memory and * backing storage. * The separate system-dependent file provides the actual backing-storage * access code, and it contains the policy decision about how much total * main memory to use. * This file is system-dependent in the sense that some of its functions * are unnecessary in some systems. For example, if there is enough virtual * memory so that backing storage will never be used, much of the virtual * array control logic could be removed. (Of course, if you have that much * memory then you shouldn't care about a little bit of unused code...) */ #define JPEG_INTERNALS #define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */ #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef NO_GETENV #ifndef HAVE_STDLIB_H /* should declare getenv() */ extern char * getenv JPP((const char * name)); #endif #endif /* * Some important notes: * The allocation routines provided here must never return NULL. * They should exit to error_exit if unsuccessful. * * It's not a good idea to try to merge the sarray and barray routines, * even though they are textually almost the same, because samples are * usually stored as bytes while coefficients are shorts or ints. Thus, * in machines where byte pointers have a different representation from * word pointers, the resulting machine code could not be the same. */ /* * Many machines require storage alignment: longs must start on 4-byte * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc() * always returns pointers that are multiples of the worst-case alignment * requirement, and we had better do so too. * There isn't any really portable way to determine the worst-case alignment * requirement. This code assumes that the alignment requirement is * multiples of SIZEOF(align_type). Here we define align_type as double; * with this definition, the code will run on all machines known to me. * If your machine has lesser alignment needs, you can save a few bytes * by making align_type smaller. */ typedef double align_type; /* * We allocate objects from "pools", where each pool is gotten with a single * request to jpeg_get_small() or jpeg_get_large(). There is no per-object * overhead within a pool, except for alignment padding. Each pool has a * header with a link to the next pool of the same class. * Small and large pool headers are identical except that the latter's * link pointer must be FAR on 80x86 machines. * Notice that the "real" header fields are union'ed with a dummy align_type * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple * of the alignment requirement of align_type. */ typedef union small_pool_struct * small_pool_ptr; typedef union small_pool_struct { struct { small_pool_ptr next; /* next in list of pools */ size_t bytes_used; /* how many bytes already used within pool */ size_t bytes_left; /* bytes still available in this pool */ } hdr; align_type dummy; /* included in union to ensure alignment */ } small_pool_hdr; typedef union large_pool_struct FAR * large_pool_ptr; typedef union large_pool_struct { struct { large_pool_ptr next; /* next in list of pools */ size_t bytes_used; /* how many bytes already used within pool */ size_t bytes_left; /* bytes still available in this pool */ } hdr; align_type dummy; /* included in union to ensure alignment */ } large_pool_hdr; /* * Here is the full definition of a memory manager object. */ typedef struct { struct jpeg_memory_mgr pub; /* public fields */ /* Each pool identifier (lifetime class) names a linked list of pools. */ small_pool_ptr small_list[JPOOL_NUMPOOLS]; large_pool_ptr large_list[JPOOL_NUMPOOLS]; /* Since we only have one lifetime class of virtual arrays, only one * linked list is necessary (for each datatype). Note that the virtual * array control blocks being linked together are actually stored somewhere * in the small-pool list. */ jvirt_sarray_ptr virt_sarray_list; jvirt_barray_ptr virt_barray_list; /* This counts total space obtained from jpeg_get_small/large */ long total_space_allocated; /* alloc_sarray and alloc_barray set this value for use by virtual * array routines. */ JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */ } my_memory_mgr; typedef my_memory_mgr * my_mem_ptr; #ifdef MEM_STATS /* optional extra stuff for statistics */ LOCAL void print_mem_stats (j_common_ptr cinfo, int pool_id) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr shdr_ptr; large_pool_ptr lhdr_ptr; /* Since this is only a debugging stub, we can cheat a little by using * fprintf directly rather than going through the trace message code. * This is helpful because message parm array can't handle longs. */ fprintf(stderr, "Freeing pool %d, total space = %ld\n", pool_id, mem->total_space_allocated); for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL; lhdr_ptr = lhdr_ptr->hdr.next) { fprintf(stderr, " Large chunk used %ld\n", (long) lhdr_ptr->hdr.bytes_used); } for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL; shdr_ptr = shdr_ptr->hdr.next) { fprintf(stderr, " Small chunk used %ld free %ld\n", (long) shdr_ptr->hdr.bytes_used, (long) shdr_ptr->hdr.bytes_left); } } #endif /* MEM_STATS */ LOCAL void out_of_memory (j_common_ptr cinfo, int which) /* Report an out-of-memory error and stop execution */ /* If we compiled MEM_STATS support, report alloc requests before dying */ { #ifdef MEM_STATS cinfo->err->trace_level = 1; /* force self_destruct to report stats */ #endif ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which); } /* * Allocation of "small" objects. * * For these, we use pooled storage. When a new pool must be created, * we try to get enough space for the current request plus a "slop" factor, * where the slop will be the amount of leftover space in the new pool. * The speed vs. space tradeoff is largely determined by the slop values. * A different slop value is provided for each pool class (lifetime), * and we also distinguish the first pool of a class from later ones. * We scale all the constants by SIZEOF(int) as a crude way of adapting * the slop constants to a particular machine. * TO DO: tune slop constants to match observed behavior of JPEG library. * May need to distinguish compression and decompression cases??? */ static const size_t first_pool_slop[JPOOL_NUMPOOLS] = { 3100 * SIZEOF(int), /* first PERMANENT pool */ 512 * SIZEOF(int) /* first IMAGE pool */ }; static const size_t extra_pool_slop[JPOOL_NUMPOOLS] = { 128 * SIZEOF(int), /* additional PERMANENT pools */ 256 * SIZEOF(int) /* additional IMAGE pools */ }; #define MIN_SLOP 50 /* greater than 0 to avoid futile looping */ METHODDEF void * alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject) /* Allocate a "small" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr hdr_ptr, prev_hdr_ptr; char * data_ptr; size_t odd_bytes, min_request, slop; /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr))) out_of_memory(cinfo, 1); /* request exceeds malloc's ability */ /* Round up the requested size to a multiple of SIZEOF(align_type) */ odd_bytes = sizeofobject % SIZEOF(align_type); if (odd_bytes > 0) sizeofobject += SIZEOF(align_type) - odd_bytes; /* See if space is available in any existing pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ prev_hdr_ptr = NULL; hdr_ptr = mem->small_list[pool_id]; while (hdr_ptr != NULL) { if (hdr_ptr->hdr.bytes_left >= sizeofobject) break; /* found pool with enough space */ prev_hdr_ptr = hdr_ptr; hdr_ptr = hdr_ptr->hdr.next; } /* Time to make a new pool? */ if (hdr_ptr == NULL) { /* min_request is what we need now, slop is what will be leftover */ min_request = sizeofobject + SIZEOF(small_pool_hdr); if (prev_hdr_ptr == NULL) /* first pool in class? */ slop = first_pool_slop[pool_id]; else slop = extra_pool_slop[pool_id]; /* Don't ask for more than MAX_ALLOC_CHUNK */ if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request)) slop = (size_t) (MAX_ALLOC_CHUNK-min_request); /* Try to get space, if fail reduce slop and try again */ for (;;) { hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop); if (hdr_ptr != NULL) break; slop /= 2; if (slop < MIN_SLOP) /* give up when it gets real small */ out_of_memory(cinfo, 2); /* jpeg_get_small failed */ } mem->total_space_allocated += min_request + slop; /* Success, initialize the new pool header and add to end of list */ hdr_ptr->hdr.next = NULL; hdr_ptr->hdr.bytes_used = 0; hdr_ptr->hdr.bytes_left = sizeofobject + slop; if (prev_hdr_ptr == NULL) /* first pool in class? */ mem->small_list[pool_id] = hdr_ptr; else prev_hdr_ptr->hdr.next = hdr_ptr; } /* OK, allocate the object from the current pool */ data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */ data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */ hdr_ptr->hdr.bytes_used += sizeofobject; hdr_ptr->hdr.bytes_left -= sizeofobject; return (void *) data_ptr; } /* * Allocation of "large" objects. * * The external semantics of these are the same as "small" objects, * except that FAR pointers are used on 80x86. However the pool * management heuristics are quite different. We assume that each * request is large enough that it may as well be passed directly to * jpeg_get_large; the pool management just links everything together * so that we can free it all on demand. * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY * structures. The routines that create these structures (see below) * deliberately bunch rows together to ensure a large request size. */ METHODDEF void FAR * alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject) /* Allocate a "large" object */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; large_pool_ptr hdr_ptr; size_t odd_bytes; /* Check for unsatisfiable request (do now to ensure no overflow below) */ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr))) out_of_memory(cinfo, 3); /* request exceeds malloc's ability */ /* Round up the requested size to a multiple of SIZEOF(align_type) */ odd_bytes = sizeofobject % SIZEOF(align_type); if (odd_bytes > 0) sizeofobject += SIZEOF(align_type) - odd_bytes; /* Always make a new pool */ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject + SIZEOF(large_pool_hdr)); if (hdr_ptr == NULL) out_of_memory(cinfo, 4); /* jpeg_get_large failed */ mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr); /* Success, initialize the new pool header and add to list */ hdr_ptr->hdr.next = mem->large_list[pool_id]; /* We maintain space counts in each pool header for statistical purposes, * even though they are not needed for allocation. */ hdr_ptr->hdr.bytes_used = sizeofobject; hdr_ptr->hdr.bytes_left = 0; mem->large_list[pool_id] = hdr_ptr; return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */ } /* * Creation of 2-D sample arrays. * The pointers are in near heap, the samples themselves in FAR heap. * * To minimize allocation overhead and to allow I/O of large contiguous * blocks, we allocate the sample rows in groups of as many rows as possible * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request. * NB: the virtual array control routines, later in this file, know about * this chunking of rows. The rowsperchunk value is left in the mem manager * object so that it can be saved away if this sarray is the workspace for * a virtual array. */ METHODDEF JSAMPARRAY alloc_sarray (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows) /* Allocate a 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JSAMPARRAY result; JSAMPROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / ((long) samplesperrow * SIZEOF(JSAMPLE)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) rowsperchunk = (JDIMENSION) ltemp; else rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; /* Get space for row pointers (small object) */ result = (JSAMPARRAY) alloc_small(cinfo, pool_id, (size_t) (numrows * SIZEOF(JSAMPROW))); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JSAMPROW) alloc_large(cinfo, pool_id, (size_t) (rowsperchunk * samplesperrow * SIZEOF(JSAMPLE))); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += samplesperrow; } } return result; } /* * Creation of 2-D coefficient-block arrays. * This is essentially the same as the code for sample arrays, above. */ METHODDEF JBLOCKARRAY alloc_barray (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows) /* Allocate a 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; JBLOCKARRAY result; JBLOCKROW workspace; JDIMENSION rowsperchunk, currow, i; long ltemp; /* Calculate max # of rows allowed in one allocation chunk */ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) / ((long) blocksperrow * SIZEOF(JBLOCK)); if (ltemp <= 0) ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); if (ltemp < (long) numrows) rowsperchunk = (JDIMENSION) ltemp; else rowsperchunk = numrows; mem->last_rowsperchunk = rowsperchunk; /* Get space for row pointers (small object) */ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id, (size_t) (numrows * SIZEOF(JBLOCKROW))); /* Get the rows themselves (large objects) */ currow = 0; while (currow < numrows) { rowsperchunk = MIN(rowsperchunk, numrows - currow); workspace = (JBLOCKROW) alloc_large(cinfo, pool_id, (size_t) (rowsperchunk * blocksperrow * SIZEOF(JBLOCK))); for (i = rowsperchunk; i > 0; i--) { result[currow++] = workspace; workspace += blocksperrow; } } return result; } /* * About virtual array management: * * To allow machines with limited memory to handle large images, all * processing in the JPEG system is done a few pixel or block rows at a time. * The above "small" array routines are only used to allocate strip buffers * (as wide as the image, but just a few rows high). * In some cases multiple passes must be made over the data. In these * cases the virtual array routines are used. The array is still accessed * a strip at a time, but the memory manager must save the whole array * for repeated accesses. The intended implementation is that there is * a strip buffer in memory (as high as is possible given the desired memory * limit), plus a backing file that holds the rest of the array. * * The request_virt_array routines are told the total size of the image and * the unit height, which is the number of rows that will be accessed at once; * the in-memory buffer should be made a multiple of this height for best * efficiency. * * The request routines create control blocks but not the in-memory buffers. * That is postponed until realize_virt_arrays is called. At that time the * total amount of space needed is known (approximately, anyway), so free * memory can be divided up fairly. * * The access_virt_array routines are responsible for making a specific strip * area accessible (after reading or writing the backing file, if necessary). * Note that the access routines are told whether the caller intends to modify * the accessed strip; during a read-only pass this saves having to rewrite * data to disk. * * The typical access pattern is one top-to-bottom pass to write the data, * followed by one or more read-only top-to-bottom passes. However, other * access patterns may occur while reading. For example, translation of image * formats that use bottom-to-top scan order will require bottom-to-top read * passes. The memory manager need not support multiple write passes nor * funny write orders (meaning that rearranging rows must be handled while * reading data out of the virtual array, not while putting it in). THIS WILL * PROBABLY NEED TO CHANGE ... will need multiple write passes for progressive * JPEG decoding. * * In current usage, the access requests are always for nonoverlapping strips; * that is, successive access start_row numbers always differ by exactly the * unitheight. This allows fairly simple buffer dump/reload logic if the * in-memory buffer is made a multiple of the unitheight. The code below * would work with overlapping access requests, but not very efficiently. */ /* The control blocks for virtual arrays. * Note that these blocks are allocated in the "small" pool area. * System-dependent info for the associated backing store (if any) is hidden * inside the backing_store_info struct. */ struct jvirt_sarray_control { JSAMPARRAY mem_buffer; /* => the in-memory buffer */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */ JDIMENSION unitheight; /* # of rows accessed by access_virt_sarray */ JDIMENSION rows_in_mem; /* height of memory buffer */ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ JDIMENSION cur_start_row; /* first logical row # in the buffer */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ jvirt_sarray_ptr next; /* link to next virtual sarray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; struct jvirt_barray_control { JBLOCKARRAY mem_buffer; /* => the in-memory buffer */ JDIMENSION rows_in_array; /* total virtual array height */ JDIMENSION blocksperrow; /* width of array (and of memory buffer) */ JDIMENSION unitheight; /* # of rows accessed by access_virt_barray */ JDIMENSION rows_in_mem; /* height of memory buffer */ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */ JDIMENSION cur_start_row; /* first logical row # in the buffer */ boolean dirty; /* do current buffer contents need written? */ boolean b_s_open; /* is backing-store data valid? */ jvirt_barray_ptr next; /* link to next virtual barray control block */ backing_store_info b_s_info; /* System-dependent control info */ }; METHODDEF jvirt_sarray_ptr request_virt_sarray (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows, JDIMENSION unitheight) /* Request a virtual 2-D sample array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_sarray_ptr result; /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ /* Round array size up to a multiple of unitheight */ numrows = (JDIMENSION) jround_up((long) numrows, (long) unitheight); /* get control block */ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_sarray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; result->samplesperrow = samplesperrow; result->unitheight = unitheight; result->b_s_open = FALSE; /* no associated backing-store object */ result->next = mem->virt_sarray_list; /* add to list of virtual arrays */ mem->virt_sarray_list = result; return result; } METHODDEF jvirt_barray_ptr request_virt_barray (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION unitheight) /* Request a virtual 2-D coefficient-block array */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; jvirt_barray_ptr result; /* Only IMAGE-lifetime virtual arrays are currently supported */ if (pool_id != JPOOL_IMAGE) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ /* Round array size up to a multiple of unitheight */ numrows = (JDIMENSION) jround_up((long) numrows, (long) unitheight); /* get control block */ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id, SIZEOF(struct jvirt_barray_control)); result->mem_buffer = NULL; /* marks array not yet realized */ result->rows_in_array = numrows; result->blocksperrow = blocksperrow; result->unitheight = unitheight; result->b_s_open = FALSE; /* no associated backing-store object */ result->next = mem->virt_barray_list; /* add to list of virtual arrays */ mem->virt_barray_list = result; return result; } METHODDEF void realize_virt_arrays (j_common_ptr cinfo) /* Allocate the in-memory buffers for any unrealized virtual arrays */ { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; long space_per_unitheight, maximum_space, avail_mem; long unitheights, max_unitheights; jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; /* Compute the minimum space needed (unitheight rows in each buffer) * and the maximum space needed (full image height in each buffer). * These may be of use to the system-dependent jpeg_mem_available routine. */ space_per_unitheight = 0; maximum_space = 0; for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ space_per_unitheight += (long) sptr->unitheight * (long) sptr->samplesperrow * SIZEOF(JSAMPLE); maximum_space += (long) sptr->rows_in_array * (long) sptr->samplesperrow * SIZEOF(JSAMPLE); } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ space_per_unitheight += (long) bptr->unitheight * (long) bptr->blocksperrow * SIZEOF(JBLOCK); maximum_space += (long) bptr->rows_in_array * (long) bptr->blocksperrow * SIZEOF(JBLOCK); } } if (space_per_unitheight <= 0) return; /* no unrealized arrays, no work */ /* Determine amount of memory to actually use; this is system-dependent. */ avail_mem = jpeg_mem_available(cinfo, space_per_unitheight, maximum_space, mem->total_space_allocated); /* If the maximum space needed is available, make all the buffers full * height; otherwise parcel it out with the same number of unitheights * in each buffer. */ if (avail_mem >= maximum_space) max_unitheights = 1000000000L; else { max_unitheights = avail_mem / space_per_unitheight; /* If there doesn't seem to be enough space, try to get the minimum * anyway. This allows a "stub" implementation of jpeg_mem_available(). */ if (max_unitheights <= 0) max_unitheights = 1; } /* Allocate the in-memory buffers and initialize backing store as needed. */ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->mem_buffer == NULL) { /* if not realized yet */ unitheights = ((long) sptr->rows_in_array - 1L) / sptr->unitheight + 1L; if (unitheights <= max_unitheights) { /* This buffer fits in memory */ sptr->rows_in_mem = sptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ sptr->rows_in_mem = (JDIMENSION) (max_unitheights * sptr->unitheight); jpeg_open_backing_store(cinfo, & sptr->b_s_info, (long) sptr->rows_in_array * (long) sptr->samplesperrow * SIZEOF(JSAMPLE)); sptr->b_s_open = TRUE; } sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE, sptr->samplesperrow, sptr->rows_in_mem); sptr->rowsperchunk = mem->last_rowsperchunk; sptr->cur_start_row = 0; sptr->dirty = FALSE; } } for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->mem_buffer == NULL) { /* if not realized yet */ unitheights = ((long) bptr->rows_in_array - 1L) / bptr->unitheight + 1L; if (unitheights <= max_unitheights) { /* This buffer fits in memory */ bptr->rows_in_mem = bptr->rows_in_array; } else { /* It doesn't fit in memory, create backing store. */ bptr->rows_in_mem = (JDIMENSION) (max_unitheights * bptr->unitheight); jpeg_open_backing_store(cinfo, & bptr->b_s_info, (long) bptr->rows_in_array * (long) bptr->blocksperrow * SIZEOF(JBLOCK)); bptr->b_s_open = TRUE; } bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE, bptr->blocksperrow, bptr->rows_in_mem); bptr->rowsperchunk = mem->last_rowsperchunk; bptr->cur_start_row = 0; bptr->dirty = FALSE; } } } LOCAL void do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual sample array */ { long bytesperrow, file_offset, byte_count, rows, i; bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE); file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); /* Transfer no more than fits in file */ rows = MIN(rows, (long) ptr->rows_in_array - ((long) ptr->cur_start_row + i)); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } LOCAL void do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing) /* Do backing store read or write of a virtual coefficient-block array */ { long bytesperrow, file_offset, byte_count, rows, i; bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK); file_offset = ptr->cur_start_row * bytesperrow; /* Loop to read or write each allocation chunk in mem_buffer */ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) { /* One chunk, but check for short chunk at end of buffer */ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i); /* Transfer no more than fits in file */ rows = MIN(rows, (long) ptr->rows_in_array - ((long) ptr->cur_start_row + i)); if (rows <= 0) /* this chunk might be past end of file! */ break; byte_count = rows * bytesperrow; if (writing) (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); else (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info, (void FAR *) ptr->mem_buffer[i], file_offset, byte_count); file_offset += byte_count; } } METHODDEF JSAMPARRAY access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JDIMENSION start_row, boolean writable) /* Access the part of a virtual sample array starting at start_row */ /* and extending for ptr->unitheight rows. writable is true if */ /* caller intends to modify the accessed area. */ { /* debugging check */ if (start_row >= ptr->rows_in_array || ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || start_row+ptr->unitheight > ptr->cur_start_row+ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(cinfo, JERR_VIRTUAL_BUG); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_sarray_io(cinfo, ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target area is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { /* use long arithmetic here to avoid overflow & unsigned problems */ long ltemp; ltemp = (long) start_row + (long) ptr->unitheight - (long) ptr->rows_in_mem; if (ltemp < 0) ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* If reading, read in the selected part of the array. * If we are writing, we need not pre-read the selected portion, * since the access sequence constraints ensure it would be garbage. */ if (! writable) { do_sarray_io(cinfo, ptr, FALSE); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } METHODDEF JBLOCKARRAY access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr, JDIMENSION start_row, boolean writable) /* Access the part of a virtual block array starting at start_row */ /* and extending for ptr->unitheight rows. writable is true if */ /* caller intends to modify the accessed area. */ { /* debugging check */ if (start_row >= ptr->rows_in_array || ptr->mem_buffer == NULL) ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS); /* Make the desired part of the virtual array accessible */ if (start_row < ptr->cur_start_row || start_row+ptr->unitheight > ptr->cur_start_row+ptr->rows_in_mem) { if (! ptr->b_s_open) ERREXIT(cinfo, JERR_VIRTUAL_BUG); /* Flush old buffer contents if necessary */ if (ptr->dirty) { do_barray_io(cinfo, ptr, TRUE); ptr->dirty = FALSE; } /* Decide what part of virtual array to access. * Algorithm: if target address > current window, assume forward scan, * load starting at target address. If target address < current window, * assume backward scan, load so that target area is top of window. * Note that when switching from forward write to forward read, will have * start_row = 0, so the limiting case applies and we load from 0 anyway. */ if (start_row > ptr->cur_start_row) { ptr->cur_start_row = start_row; } else { /* use long arithmetic here to avoid overflow & unsigned problems */ long ltemp; ltemp = (long) start_row + (long) ptr->unitheight - (long) ptr->rows_in_mem; if (ltemp < 0) ltemp = 0; /* don't fall off front end of file */ ptr->cur_start_row = (JDIMENSION) ltemp; } /* If reading, read in the selected part of the array. * If we are writing, we need not pre-read the selected portion, * since the access sequence constraints ensure it would be garbage. */ if (! writable) { do_barray_io(cinfo, ptr, FALSE); } } /* Flag the buffer dirty if caller will write in it */ if (writable) ptr->dirty = TRUE; /* Return address of proper part of the buffer */ return ptr->mem_buffer + (start_row - ptr->cur_start_row); } /* * Release all objects belonging to a specified pool. */ METHODDEF void free_pool (j_common_ptr cinfo, int pool_id) { my_mem_ptr mem = (my_mem_ptr) cinfo->mem; small_pool_ptr shdr_ptr; large_pool_ptr lhdr_ptr; size_t space_freed; if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS) ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */ #ifdef MEM_STATS if (cinfo->err->trace_level > 0) print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */ #endif /* If freeing IMAGE pool, close any virtual arrays first */ if (pool_id == JPOOL_IMAGE) { jvirt_sarray_ptr sptr; jvirt_barray_ptr bptr; for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) { if (sptr->b_s_open) { /* there may be no backing store */ sptr->b_s_open = FALSE; /* prevent recursive close if error */ (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info); } } mem->virt_sarray_list = NULL; for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) { if (bptr->b_s_open) { /* there may be no backing store */ bptr->b_s_open = FALSE; /* prevent recursive close if error */ (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info); } } mem->virt_barray_list = NULL; } /* Release large objects */ lhdr_ptr = mem->large_list[pool_id]; mem->large_list[pool_id] = NULL; while (lhdr_ptr != NULL) { large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next; space_freed = lhdr_ptr->hdr.bytes_used + lhdr_ptr->hdr.bytes_left + SIZEOF(large_pool_hdr); jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed); mem->total_space_allocated -= space_freed; lhdr_ptr = next_lhdr_ptr; } /* Release small objects */ shdr_ptr = mem->small_list[pool_id]; mem->small_list[pool_id] = NULL; while (shdr_ptr != NULL) { small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next; space_freed = shdr_ptr->hdr.bytes_used + shdr_ptr->hdr.bytes_left + SIZEOF(small_pool_hdr); jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed); mem->total_space_allocated -= space_freed; shdr_ptr = next_shdr_ptr; } } /* * Close up shop entirely. * Note that this cannot be called unless cinfo->mem is non-NULL. */ METHODDEF void self_destruct (j_common_ptr cinfo) { int pool; /* Close all backing store, release all memory. * Releasing pools in reverse order might help avoid fragmentation * with some (brain-damaged) malloc libraries. */ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { free_pool(cinfo, pool); } /* Release the memory manager control block too. */ jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr)); cinfo->mem = NULL; /* ensures I will be called only once */ jpeg_mem_term(cinfo); /* system-dependent cleanup */ } /* * Memory manager initialization. * When this is called, only the error manager pointer is valid in cinfo! */ GLOBAL void jinit_memory_mgr (j_common_ptr cinfo) { my_mem_ptr mem; long max_to_use; int pool; cinfo->mem = NULL; /* for safety if init fails */ max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */ /* Attempt to allocate memory manager's control block */ mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr)); if (mem == NULL) { jpeg_mem_term(cinfo); /* system-dependent cleanup */ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0); } /* OK, fill in the method pointers */ mem->pub.alloc_small = alloc_small; mem->pub.alloc_large = alloc_large; mem->pub.alloc_sarray = alloc_sarray; mem->pub.alloc_barray = alloc_barray; mem->pub.request_virt_sarray = request_virt_sarray; mem->pub.request_virt_barray = request_virt_barray; mem->pub.realize_virt_arrays = realize_virt_arrays; mem->pub.access_virt_sarray = access_virt_sarray; mem->pub.access_virt_barray = access_virt_barray; mem->pub.free_pool = free_pool; mem->pub.self_destruct = self_destruct; /* Initialize working state */ mem->pub.max_memory_to_use = max_to_use; for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) { mem->small_list[pool] = NULL; mem->large_list[pool] = NULL; } mem->virt_sarray_list = NULL; mem->virt_barray_list = NULL; mem->total_space_allocated = SIZEOF(my_memory_mgr); /* Declare ourselves open for business */ cinfo->mem = & mem->pub; /* Check for an environment variable JPEGMEM; if found, override the * default max_memory setting from jpeg_mem_init. Note that the * surrounding application may again override this value. * If your system doesn't support getenv(), define NO_GETENV to disable * this feature. */ #ifndef NO_GETENV { char * memenv; if ((memenv = getenv("JPEGMEM")) != NULL) { char ch = 'x'; if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) { if (ch == 'm' || ch == 'M') max_to_use *= 1000L; mem->pub.max_memory_to_use = max_to_use * 1000L; } } } #endif } \ No newline at end of file diff --git a/Independent JPEG Group/jmemname.c b/Independent JPEG Group/jmemname.c new file mode 100644 index 0000000..cab0b7d --- /dev/null +++ b/Independent JPEG Group/jmemname.c @@ -0,0 +1 @@ +/* * jmemname.c * * Copyright (C) 1992-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a generic implementation of the system-dependent * portion of the JPEG memory manager. This implementation assumes that * you must explicitly construct a name for each temp file. * Also, the problem of determining the amount of memory available * is shoved onto the user. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); #endif #ifndef SEEK_SET /* pre-ANSI systems may not define this; */ #define SEEK_SET 0 /* if not, assume 0 is correct */ #endif #ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */ #define READ_BINARY "r" #define RW_BINARY "w+" #else #define READ_BINARY "rb" #define RW_BINARY "w+b" #endif /* * Selection of a file name for a temporary file. * This is system-dependent! * * The code as given is suitable for most Unix systems, and it is easily * modified for most non-Unix systems. Some notes: * 1. The temp file is created in the directory named by TEMP_DIRECTORY. * The default value is /usr/tmp, which is the conventional place for * creating large temp files on Unix. On other systems you'll probably * want to change the file location. You can do this by editing the * #define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h. * * 2. If you need to change the file name as well as its location, * you can override the TEMP_FILE_NAME macro. (Note that this is * actually a printf format string; it must contain %s and %d.) * Few people should need to do this. * * 3. mktemp() is used to ensure that multiple processes running * simultaneously won't select the same file names. If your system * doesn't have mktemp(), define NO_MKTEMP to do it the hard way. * * 4. You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c * will cause the temp files to be removed if you stop the program early. */ #ifndef TEMP_DIRECTORY /* can override from jconfig.h or Makefile */ #define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */ #endif static int next_file_num; /* to distinguish among several temp files */ #ifdef NO_MKTEMP #ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ #define TEMP_FILE_NAME "%sJPG%03d.TMP" #endif LOCAL void select_file_name (char * fname) { FILE * tfile; /* Keep generating file names till we find one that's not in use */ for (;;) { next_file_num++; /* advance counter */ sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); if ((tfile = fopen(fname, READ_BINARY)) == NULL) break; fclose(tfile); /* oops, it's there; close tfile & try again */ } } #else /* ! NO_MKTEMP */ /* Note that mktemp() requires the initial filename to end in six X's */ #ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */ #define TEMP_FILE_NAME "%sJPG%dXXXXXX" #endif LOCAL void select_file_name (char * fname) { next_file_num++; /* advance counter */ sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num); mktemp(fname); /* make sure file name is unique */ /* mktemp replaces the trailing XXXXXX with a unique string of characters */ } #endif /* NO_MKTEMP */ /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL void jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) { free(object); } /* * "Large" objects are treated the same as "small" ones. * NB: although we include FAR keywords in the routine declarations, * this file won't actually work in 80x86 small model. */ GLOBAL void FAR * jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) { return (void FAR *) malloc(sizeofobject); } GLOBAL void jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) { free(object); } /* * This routine computes the total memory space available for allocation. * It's impossible to do this in a portable way; our current solution is * to make the user tell us (with a default value set at compile time). * If you can actually get the available space, it's a good idea to subtract * a slop factor of 5% or so. */ #ifndef DEFAULT_MAX_MEM /* so can override from makefile */ #define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */ #endif GLOBAL long jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated) { return cinfo->mem->max_memory_to_use - already_allocated; } /* * Backing store (temporary file) management. * Backing store objects are only used when the value returned by * jpeg_mem_available is less than the total space needed. You can dispense * with these routines if you have plenty of virtual memory; see jmemnobs.c. */ METHODDEF void read_backing_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(cinfo, JERR_TFILE_SEEK); if (JFREAD(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(cinfo, JERR_TFILE_READ); } METHODDEF void write_backing_store (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count) { if (fseek(info->temp_file, file_offset, SEEK_SET)) ERREXIT(cinfo, JERR_TFILE_SEEK); if (JFWRITE(info->temp_file, buffer_address, byte_count) != (size_t) byte_count) ERREXIT(cinfo, JERR_TFILE_WRITE); } METHODDEF void close_backing_store (j_common_ptr cinfo, backing_store_ptr info) { fclose(info->temp_file); /* close the file */ unlink(info->temp_name); /* delete the file */ /* If your system doesn't have unlink(), use remove() instead. * remove() is the ANSI-standard name for this function, but if * your system was ANSI you'd be using jmemansi.c, right? */ TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name); } /* * Initial opening of a backing-store object. */ GLOBAL void jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { select_file_name(info->temp_name); if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL) ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name); info->read_backing_store = read_backing_store; info->write_backing_store = write_backing_store; info->close_backing_store = close_backing_store; TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name); } /* * These routines take care of any system-dependent initialization and * cleanup required. */ GLOBAL long jpeg_mem_init (j_common_ptr cinfo) { next_file_num = 0; /* initialize temp file name generator */ return DEFAULT_MAX_MEM; /* default for max_memory_to_use */ } GLOBAL void jpeg_mem_term (j_common_ptr cinfo) { /* no work */ } \ No newline at end of file diff --git a/Independent JPEG Group/jmemnobs.c b/Independent JPEG Group/jmemnobs.c new file mode 100644 index 0000000..73d1b94 --- /dev/null +++ b/Independent JPEG Group/jmemnobs.c @@ -0,0 +1 @@ +/* * jmemnobs.c * * Copyright (C) 1992-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides a really simple implementation of the system- * dependent portion of the JPEG memory manager. This implementation * assumes that no backing-store files are needed: all required space * can be obtained from malloc(). * This is very portable in the sense that it'll compile on almost anything, * but you'd better have lots of main memory (or virtual memory) if you want * to process big images. * Note that the max_memory_to_use option is ignored by this implementation. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #include "jmemsys.h" /* import the system-dependent declarations */ #ifndef HAVE_STDLIB_H /* should declare malloc(),free() */ extern void * malloc JPP((size_t size)); extern void free JPP((void *ptr)); #endif /* * Memory allocation and freeing are controlled by the regular library * routines malloc() and free(). */ GLOBAL void * jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject) { return (void *) malloc(sizeofobject); } GLOBAL void jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject) { free(object); } /* * "Large" objects are treated the same as "small" ones. * NB: although we include FAR keywords in the routine declarations, * this file won't actually work in 80x86 small model. */ GLOBAL void FAR * jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject) { return (void FAR *) malloc(sizeofobject); } GLOBAL void jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject) { free(object); } /* * This routine computes the total memory space available for allocation. * Here we always say, "we got all you want bud!" */ GLOBAL long jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated) { return max_bytes_needed; } /* * Backing store (temporary file) management. * Since jpeg_mem_available always promised the moon, * this should never be called and we can just error out. */ GLOBAL void jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed) { ERREXIT(cinfo, JERR_NO_BACKING_STORE); } /* * These routines take care of any system-dependent initialization and * cleanup required. Here, there isn't any. */ GLOBAL long jpeg_mem_init (j_common_ptr cinfo) { return 0; /* just set max_memory_to_use to 0 */ } GLOBAL void jpeg_mem_term (j_common_ptr cinfo) { /* no work */ } \ No newline at end of file diff --git a/Independent JPEG Group/jmemsys.h b/Independent JPEG Group/jmemsys.h new file mode 100644 index 0000000..2e9911c --- /dev/null +++ b/Independent JPEG Group/jmemsys.h @@ -0,0 +1 @@ +/* * jmemsys.h * * Copyright (C) 1992-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This include file defines the interface between the system-independent * and system-dependent portions of the JPEG memory manager. No other * modules need include it. (The system-independent portion is jmemmgr.c; * there are several different versions of the system-dependent portion.) * * This file works as-is for the system-dependent memory managers supplied * in the IJG distribution. You may need to modify it if you write a * custom memory manager. If system-dependent changes are needed in * this file, the best method is to #ifdef them based on a configuration * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR. */ /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_get_small jGetSmall #define jpeg_free_small jFreeSmall #define jpeg_get_large jGetLarge #define jpeg_free_large jFreeLarge #define jpeg_mem_available jMemAvail #define jpeg_open_backing_store jOpenBackStore #define jpeg_mem_init jMemInit #define jpeg_mem_term jMemTerm #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* * These two functions are used to allocate and release small chunks of * memory. (Typically the total amount requested through jpeg_get_small is * no more than 20K or so; this will be requested in chunks of a few K each.) * Behavior should be the same as for the standard library functions malloc * and free; in particular, jpeg_get_small must return NULL on failure. * On most systems, these ARE malloc and free. jpeg_free_small is passed the * size of the object being freed, just in case it's needed. * On an 80x86 machine using small-data memory model, these manage near heap. */ EXTERN void * jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject)); EXTERN void jpeg_free_small JPP((j_common_ptr cinfo, void * object, size_t sizeofobject)); /* * These two functions are used to allocate and release large chunks of * memory (up to the total free space designated by jpeg_mem_available). * The interface is the same as above, except that on an 80x86 machine, * far pointers are used. On most other machines these are identical to * the jpeg_get/free_small routines; but we keep them separate anyway, * in case a different allocation strategy is desirable for large chunks. */ EXTERN void FAR * jpeg_get_large JPP((j_common_ptr cinfo,size_t sizeofobject)); EXTERN void jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object, size_t sizeofobject)); /* * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may * be requested in a single call to jpeg_get_large (and jpeg_get_small for that * matter, but that case should never come into play). This macro is needed * to model the 64Kb-segment-size limit of far addressing on 80x86 machines. * On those machines, we expect that jconfig.h will provide a proper value. * On machines with 32-bit flat address spaces, any large constant may be used. * * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type * size_t and will be a multiple of sizeof(align_type). */ #ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */ #define MAX_ALLOC_CHUNK 1000000000L #endif /* * This routine computes the total space still available for allocation by * jpeg_get_large. If more space than this is needed, backing store will be * used. NOTE: any memory already allocated must not be counted. * * There is a minimum space requirement, corresponding to the minimum * feasible buffer sizes; jmemmgr.c will request that much space even if * jpeg_mem_available returns zero. The maximum space needed, enough to hold * all working storage in memory, is also passed in case it is useful. * Finally, the total space already allocated is passed. If no better * method is available, cinfo->mem->max_memory_to_use - already_allocated * is often a suitable calculation. * * It is OK for jpeg_mem_available to underestimate the space available * (that'll just lead to more backing-store access than is really necessary). * However, an overestimate will lead to failure. Hence it's wise to subtract * a slop factor from the true available space. 5% should be enough. * * On machines with lots of virtual memory, any large constant may be returned. * Conversely, zero may be returned to always use the minimum amount of memory. */ EXTERN long jpeg_mem_available JPP((j_common_ptr cinfo, long min_bytes_needed, long max_bytes_needed, long already_allocated)); /* * This structure holds whatever state is needed to access a single * backing-store object. The read/write/close method pointers are called * by jmemmgr.c to manipulate the backing-store object; all other fields * are private to the system-dependent backing store routines. */ #define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */ #ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */ typedef unsigned short XMSH; /* type of extended-memory handles */ typedef unsigned short EMSH; /* type of expanded-memory handles */ typedef union { short file_handle; /* DOS file handle if it's a temp file */ XMSH xms_handle; /* handle if it's a chunk of XMS */ EMSH ems_handle; /* handle if it's a chunk of EMS */ } handle_union; #endif /* USE_MSDOS_MEMMGR */ typedef struct backing_store_struct * backing_store_ptr; typedef struct backing_store_struct { /* Methods for reading/writing/closing this backing-store object */ JMETHOD(void, read_backing_store, (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); JMETHOD(void, write_backing_store, (j_common_ptr cinfo, backing_store_ptr info, void FAR * buffer_address, long file_offset, long byte_count)); JMETHOD(void, close_backing_store, (j_common_ptr cinfo, backing_store_ptr info)); /* Private fields for system-dependent backing-store management */ #ifdef USE_MSDOS_MEMMGR /* For the MS-DOS manager (jmemdos.c), we need: */ handle_union handle; /* reference to backing-store storage object */ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */ #else /* For a typical implementation with temp files, we need: */ FILE * temp_file; /* stdio reference to temp file */ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */ #endif } backing_store_info; /* * Initial opening of a backing-store object. This must fill in the * read/write/close pointers in the object. The read/write routines * may take an error exit if the specified maximum file size is exceeded. * (If jpeg_mem_available always returns a large value, this routine can * just take an error exit.) */ EXTERN void jpeg_open_backing_store JPP((j_common_ptr cinfo, backing_store_ptr info, long total_bytes_needed)); /* * These routines take care of any system-dependent initialization and * cleanup required. jpeg_mem_init will be called before anything is * allocated (and, therefore, nothing in cinfo is of use except the error * manager pointer). It should return a suitable default value for * max_memory_to_use; this may subsequently be overridden by the surrounding * application. (Note that max_memory_to_use is only important if * jpeg_mem_available chooses to consult it ... no one else will.) * jpeg_mem_term may assume that all requested memory has been freed and that * all opened backing-store objects have been closed. */ EXTERN long jpeg_mem_init JPP((j_common_ptr cinfo)); EXTERN void jpeg_mem_term JPP((j_common_ptr cinfo)); \ No newline at end of file diff --git a/Independent JPEG Group/jmorecfg.h b/Independent JPEG Group/jmorecfg.h new file mode 100644 index 0000000..fae88c2 --- /dev/null +++ b/Independent JPEG Group/jmorecfg.h @@ -0,0 +1 @@ +/* * jmorecfg.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains additional configuration options that customize the * JPEG software for special applications or support machine-dependent * optimizations. Most users will not need to touch this file. */ /* * Define BITS_IN_JSAMPLE as either * 8 for 8-bit sample values (the usual setting) * 12 for 12-bit sample values * Only 8 and 12 are legal data precisions for lossy JPEG according to the * JPEG standard, and the IJG code does not support anything else! * We do not support run-time selection of data precision, sorry. */ #define BITS_IN_JSAMPLE 8 /* use 8 or 12 */ /* * Maximum number of components (color channels) allowed in JPEG image. * To meet the letter of the JPEG spec, set this to 255. However, darn * few applications need more than 4 channels (maybe 5 for CMYK + alpha * mask). We recommend 10 as a reasonable compromise; use 4 if you are * really short on memory. (Each allowed component costs a hundred or so * bytes of storage, whether actually used in an image or not.) */ #define MAX_COMPONENTS 10 /* maximum number of image components */ /* * Basic data types. * You may need to change these if you have a machine with unusual data * type sizes; for example, "char" not 8 bits, "short" not 16 bits, * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits, * but it had better be at least 16. */ /* Representation of a single sample (pixel element value). * We frequently allocate large arrays of these, so it's important to keep * them small. But if you have memory to burn and access to char or short * arrays is very slow on your hardware, you might want to change these. */ #if BITS_IN_JSAMPLE == 8 /* JSAMPLE should be the smallest type that will hold the values 0..255. * You can use a signed char by having GETJSAMPLE mask it with 0xFF. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JSAMPLE; #define GETJSAMPLE(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JSAMPLE; #ifdef CHAR_IS_UNSIGNED #define GETJSAMPLE(value) (value) #else #define GETJSAMPLE(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ #define MAXJSAMPLE 255 #define CENTERJSAMPLE 128 #endif /* BITS_IN_JSAMPLE == 8 */ #if BITS_IN_JSAMPLE == 12 /* JSAMPLE should be the smallest type that will hold the values 0..4095. * On nearly all machines "short" will do nicely. */ typedef short JSAMPLE; #define GETJSAMPLE(value) (value) #define MAXJSAMPLE 4095 #define CENTERJSAMPLE 2048 #endif /* BITS_IN_JSAMPLE == 12 */ /* Representation of a DCT frequency coefficient. * This should be a signed value of at least 16 bits; "short" is usually OK. * Again, we allocate large arrays of these, but you can change to int * if you have memory to burn and "short" is really slow. */ typedef short JCOEF; /* Compressed datastreams are represented as arrays of JOCTET. * These must be EXACTLY 8 bits wide, at least once they are written to * external storage. Note that when using the stdio data source/destination * managers, this is also the data type passed to fread/fwrite. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char JOCTET; #define GETJOCTET(value) (value) #else /* not HAVE_UNSIGNED_CHAR */ typedef char JOCTET; #ifdef CHAR_IS_UNSIGNED #define GETJOCTET(value) (value) #else #define GETJOCTET(value) ((value) & 0xFF) #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* These typedefs are used for various table entries and so forth. * They must be at least as wide as specified; but making them too big * won't cost a huge amount of memory, so we don't provide special * extraction code like we did for JSAMPLE. (In other words, these * typedefs live at a different point on the speed/space tradeoff curve.) */ /* UINT8 must hold at least the values 0..255. */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char UINT8; #else /* not HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char UINT8; #else /* not CHAR_IS_UNSIGNED */ typedef short UINT8; #endif /* CHAR_IS_UNSIGNED */ #endif /* HAVE_UNSIGNED_CHAR */ /* UINT16 must hold at least the values 0..65535. */ #ifdef HAVE_UNSIGNED_SHORT typedef unsigned short UINT16; #else /* not HAVE_UNSIGNED_SHORT */ typedef unsigned int UINT16; #endif /* HAVE_UNSIGNED_SHORT */ /* INT16 must hold at least the values -32768..32767. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT16 */ typedef short INT16; #endif /* INT32 must hold at least signed 32-bit values. */ #ifndef XMD_H /* X11/xmd.h correctly defines INT32 */ typedef long INT32; #endif /* Datatype used for image dimensions. The JPEG standard only supports * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore * "unsigned int" is sufficient on all machines. However, if you need to * handle larger images and you don't mind deviating from the spec, you * can change this datatype. */ typedef unsigned int JDIMENSION; #define JPEG_MAX_DIMENSION 65500 /* a tad under 64K to prevent overflows */ /* These defines are used in all function definitions and extern declarations. * You could modify them if you need to change function linkage conventions. * Another application is to make all functions global for use with debuggers * or code profilers that require it. */ #define METHODDEF static /* a function called through method pointers */ #define LOCAL static /* a function used only in its module */ #define GLOBAL /* a function referenced thru EXTERNs */ #define EXTERN extern /* a reference to a GLOBAL function */ /* Here is the pseudo-keyword for declaring pointers that must be "far" * on 80x86 machines. Most of the specialized coding for 80x86 is handled * by just saying "FAR *" where such a pointer is needed. In a few places * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol. */ #ifdef NEED_FAR_POINTERS #define FAR far #else #define FAR #endif /* * On a few systems, type boolean and/or its values FALSE, TRUE may appear * in standard header files. Or you may have conflicts with application- * specific header files that you want to include together with these files. * Defining HAVE_BOOLEAN before including jpeglib.h should make it work. */ #ifndef HAVE_BOOLEAN typedef int boolean; #endif #ifndef FALSE /* in case these macros already exist */ #define FALSE 0 /* values of boolean */ #endif #ifndef TRUE #define TRUE 1 #endif /* * The following options affect code selection within the JPEG library, * but they don't need to be visible to applications using the library. * To minimize application namespace pollution, the symbols won't be * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined. */ #ifdef JPEG_INTERNALS #define JPEG_INTERNAL_OPTIONS #endif #ifdef JPEG_INTERNAL_OPTIONS /* * These defines indicate whether to include various optional functions. * Undefining some of these symbols will produce a smaller but less capable * library. Note that you can leave certain source files out of the * compilation/linking process if you've #undef'd the corresponding symbols. * (You may HAVE to do that if your compiler doesn't like null source files.) */ /* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */ /* Encoder capability options: */ #undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #undef C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? (NYI) */ #define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */ /* Note: if you selected 12-bit data precision, it is dangerous to turn off * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit * precision, so jchuff.c normally uses entropy optimization to compute * usable tables for higher precision. If you don't want to do optimization, * you'll have to supply different default Huffman tables. */ #undef INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */ /* Decoder capability options: */ #undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */ #undef D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */ #define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */ #undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */ #undef BLOCK_SMOOTHING_SUPPORTED /* Block smoothing during decoding? */ #undef QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */ // CHANGED! #undef'ed #undef QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */ // CHANGED! #undef'ed /* more capability options later, no doubt */ /* If your compiler supports inline functions, define INLINE * as the inline keyword; otherwise define it as empty. */ #ifndef INLINE #ifdef __GNUC__ /* for instance, GNU C knows about inline */ #define INLINE __inline__ #endif #ifndef INLINE #define INLINE /* default is to define it as empty */ #endif #endif /* Typedef for multiplying quantized coefficients by pre-IDCT multipliers. * Must be a signed type. Use short if short*short is faster than int*int. */ #if BITS_IN_JSAMPLE == 8 typedef int MULTIPLIER; /* may want short on some machines */ #else typedef INT32 MULTIPLIER; /* need more than 16 bits in this case */ #endif #endif /* JPEG_INTERNAL_OPTIONS */ \ No newline at end of file diff --git a/Independent JPEG Group/jpegint.h b/Independent JPEG Group/jpegint.h new file mode 100644 index 0000000..39c47a2 --- /dev/null +++ b/Independent JPEG Group/jpegint.h @@ -0,0 +1 @@ +/* * jpegint.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file provides common declarations for the various JPEG modules. * These declarations are considered internal to the JPEG library; most * applications using the library shouldn't need to include this file. */ /* Declarations for both compression & decompression */ typedef enum { /* Operating modes for buffer controllers */ JBUF_PASS_THRU, /* Plain stripwise operation */ JBUF_CRANK_SOURCE, /* Run source subobject only, no output */ /* Remaining modes require a full-image buffer to have been created */ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */ } J_BUF_MODE; /* Values of global_state field */ #define CSTATE_START 100 /* after create_compress */ #define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */ #define DSTATE_START 200 /* after create_decompress */ #define DSTATE_INHEADER 201 /* read_header initialized but not done */ #define DSTATE_READY 202 /* read_header done, found image */ #define DSTATE_SCANNING 203 /* start_decompress done, read_scanlines OK */ #define DSTATE_STOPPING 204 /* done reading data, looking for EOI */ /* Declarations for compression modules */ /* Master control module */ struct jpeg_comp_master { JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo)); JMETHOD(void, pass_startup, (j_compress_ptr cinfo)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); /* State variables made visible to other modules */ boolean call_pass_startup; /* True if pass_startup must be called */ boolean is_last_pass; /* True during last pass */ }; /* Main buffer control (downsampled-data buffer) */ struct jpeg_c_main_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); }; /* Compression preprocessing (downsampling input buffer control) */ struct jpeg_c_prep_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, pre_process_data, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail, JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, JDIMENSION out_row_groups_avail)); }; /* Coefficient buffer control */ struct jpeg_c_coef_controller { JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, compress_data, (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_mcu_ctr)); }; /* Colorspace conversion */ struct jpeg_color_converter { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, color_convert, (j_compress_ptr cinfo, JSAMPARRAY input_buf, JSAMPIMAGE output_buf, JDIMENSION output_row, int num_rows)); }; /* Downsampling */ struct jpeg_downsampler { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); JMETHOD(void, downsample, (j_compress_ptr cinfo, JSAMPIMAGE input_buf, JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)); boolean need_context_rows; /* TRUE if need rows above & below */ }; /* Forward DCT (also controls coefficient quantization) */ struct jpeg_forward_dct { JMETHOD(void, start_pass, (j_compress_ptr cinfo)); /* perhaps this should be an array??? */ JMETHOD(void, forward_DCT, (j_compress_ptr cinfo, jpeg_component_info * compptr, JSAMPARRAY sample_data, JBLOCKROW coef_blocks, JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks)); }; /* JCQUANT_TBL details made visible for jpeg_alloc_quant_table */ typedef struct { JQUANT_TBL pub; /* public fields */ /* Extra data for encoding */ /* The actual pre-DCT divisors -- may differ from quantizer values */ /* found in the DQT marker, if an unnormalized DCT is used. */ /* Given in zigzag order. */ MULTIPLIER divisors[DCTSIZE2]; } JCQUANT_TBL; /* Entropy encoding */ struct jpeg_entropy_encoder { JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics)); JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data)); JMETHOD(void, finish_pass, (j_compress_ptr cinfo)); }; /* JCHUFF_TBL details made visible for jpeg_alloc_huff_table */ typedef struct { JHUFF_TBL pub; /* public fields */ /* Extra data for Huffman encoder's use only */ unsigned int ehufco[256]; /* code for each symbol */ char ehufsi[256]; /* length of code for each symbol */ } JCHUFF_TBL; /* Marker writing */ struct jpeg_marker_writer { /* write_any_marker is exported for use by applications */ /* Probably only COM and APPn markers should be written */ JMETHOD(void, write_any_marker, (j_compress_ptr cinfo, int marker, JOCTET *dataptr, unsigned int datalen)); JMETHOD(void, write_file_header, (j_compress_ptr cinfo)); JMETHOD(void, write_frame_header, (j_compress_ptr cinfo)); JMETHOD(void, write_scan_header, (j_compress_ptr cinfo)); JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo)); JMETHOD(void, write_tables_only, (j_compress_ptr cinfo)); }; /* Declarations for decompression modules */ /* Master control module */ struct jpeg_decomp_master { JMETHOD(void, prepare_for_pass, (j_decompress_ptr cinfo)); JMETHOD(void, finish_pass, (j_decompress_ptr cinfo)); /* State variables made visible to other modules */ boolean is_last_pass; /* True during last pass */ boolean eoi_processed; /* True if EOI marker already read */ }; /* Main buffer control (downsampled-data buffer) */ struct jpeg_d_main_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, process_data, (j_decompress_ptr cinfo, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); }; /* Coefficient buffer control */ struct jpeg_d_coef_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(boolean, decompress_data, (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)); }; /* Decompression postprocessing (color quantization buffer control) */ struct jpeg_d_post_controller { JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)); JMETHOD(void, post_process_data, (j_decompress_ptr cinfo, JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr, JDIMENSION in_row_groups_avail, JSAMPARRAY output_buf, JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail)); }; /* Marker reading & parsing */ typedef JMETHOD(boolean, marker_parser_method_ptr, (j_decompress_ptr cinfo)); /* Need not pass marker code since it is stored in cinfo->unread_marker. */ struct jpeg_marker_reader { JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo)); /* Read markers until SOS or EOI. * Returns same codes as are defined for jpeg_read_header, * but HEADER_OK and HEADER_TABLES_ONLY merely indicate which marker type * stopped the scan --- further validation is needed to declare file OK. */ JMETHOD(int, read_markers, (j_decompress_ptr cinfo)); /* Read a restart marker --- exported for use by entropy decoder only */ marker_parser_method_ptr read_restart_marker; /* Application-overridable marker processing methods */ marker_parser_method_ptr process_COM; marker_parser_method_ptr process_APPn[16]; /* State of marker reader --- nominally internal, but applications * supplying COM or APPn handlers might like to know the state. */ boolean saw_SOI; /* found SOI? */ boolean saw_SOF; /* found SOF? */ int next_restart_num; /* next restart number expected (0-7) */ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */ }; /* Entropy decoding */ struct jpeg_entropy_decoder { JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)); }; /* JDHUFF_TBL details made visible for jpeg_alloc_huff_table */ #define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */ typedef struct { JHUFF_TBL pub; /* public fields */ /* Extra data for Huffman decoder's use only */ /* Basic tables: (element [0] of each array is unused) */ INT32 mincode[17]; /* smallest code of length k */ INT32 maxcode[18]; /* largest code of length k (-1 if none) */ /* (maxcode[17] is a sentinel to ensure huff_DECODE terminates) */ int valptr[17]; /* huffval[] index of 1st symbol of length k */ /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of * the input data stream. If the next Huffman code is no more * than HUFF_LOOKAHEAD bits long, we can obtain its length and * the corresponding symbol directly from these tables. */ int look_nbits[1< (b) ? (a) : (b)) #undef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) /* We assume that right shift corresponds to signed division by 2 with * rounding towards minus infinity. This is correct for typical "arithmetic * shift" instructions that shift in copies of the sign bit. But some * C compilers implement >> with an unsigned shift. For these machines you * must define RIGHT_SHIFT_IS_UNSIGNED. * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. * It is only applied with constant shift counts. SHIFT_TEMPS must be * included in the variables of any routine using RIGHT_SHIFT. */ #ifdef RIGHT_SHIFT_IS_UNSIGNED #define SHIFT_TEMPS INT32 shift_temp; #define RIGHT_SHIFT(x,shft) \ ((shift_temp = (x)) < 0 ? \ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ (shift_temp >> (shft))) #else #define SHIFT_TEMPS #define RIGHT_SHIFT(x,shft) ((x) >> (shft)) #endif /* Short forms of external names for systems with brain-damaged linkers. */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jinit_master_compress jICMaster #define jinit_c_main_controller jICMainC #define jinit_c_prep_controller jICPrepC #define jinit_c_coef_controller jICCoefC #define jinit_color_converter jICColor #define jinit_downsampler jIDownsampler #define jinit_forward_dct jIFDCT #define jinit_huff_encoder jIHEncoder #define jinit_marker_writer jIMWriter #define jinit_master_decompress jIDMaster #define jinit_d_main_controller jIDMainC #define jinit_d_coef_controller jIDCoefC #define jinit_d_post_controller jIDPostC #define jinit_marker_reader jIMReader #define jinit_huff_decoder jIHDecoder #define jinit_inverse_dct jIIDCT #define jinit_upsampler jIUpsampler #define jinit_color_deconverter jIDColor #define jinit_1pass_quantizer jI1Quant #define jinit_2pass_quantizer jI2Quant #define jinit_memory_mgr jIMemMgr #define jdiv_round_up jDivRound #define jround_up jRound #define jcopy_sample_rows jCopySamples #define jcopy_block_row jCopyBlocks #define jzero_far jZeroFar #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Compression module initialization routines */ EXTERN void jinit_master_compress JPP((j_compress_ptr cinfo)); EXTERN void jinit_c_main_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN void jinit_c_prep_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN void jinit_c_coef_controller JPP((j_compress_ptr cinfo, boolean need_full_buffer)); EXTERN void jinit_color_converter JPP((j_compress_ptr cinfo)); EXTERN void jinit_downsampler JPP((j_compress_ptr cinfo)); EXTERN void jinit_forward_dct JPP((j_compress_ptr cinfo)); EXTERN void jinit_huff_encoder JPP((j_compress_ptr cinfo)); EXTERN void jinit_marker_writer JPP((j_compress_ptr cinfo)); /* Decompression module initialization routines */ EXTERN void jinit_master_decompress JPP((j_decompress_ptr cinfo)); EXTERN void jinit_d_main_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN void jinit_d_coef_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN void jinit_d_post_controller JPP((j_decompress_ptr cinfo, boolean need_full_buffer)); EXTERN void jinit_marker_reader JPP((j_decompress_ptr cinfo)); EXTERN void jinit_huff_decoder JPP((j_decompress_ptr cinfo)); EXTERN void jinit_inverse_dct JPP((j_decompress_ptr cinfo)); EXTERN void jinit_upsampler JPP((j_decompress_ptr cinfo)); EXTERN void jinit_color_deconverter JPP((j_decompress_ptr cinfo)); EXTERN void jinit_1pass_quantizer JPP((j_decompress_ptr cinfo)); EXTERN void jinit_2pass_quantizer JPP((j_decompress_ptr cinfo)); /* Memory manager initialization */ EXTERN void jinit_memory_mgr JPP((j_common_ptr cinfo)); /* Utility routines in jutils.c */ EXTERN long jdiv_round_up JPP((long a, long b)); EXTERN long jround_up JPP((long a, long b)); EXTERN void jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols)); EXTERN void jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks)); EXTERN void jzero_far JPP((void FAR * target, size_t bytestozero)); /* Suppress undefined-structure complaints if necessary. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */ struct jvirt_sarray_control { long dummy; }; struct jvirt_barray_control { long dummy; }; #endif #endif /* INCOMPLETE_TYPES_BROKEN */ \ No newline at end of file diff --git a/Independent JPEG Group/jpeglib.h b/Independent JPEG Group/jpeglib.h new file mode 100644 index 0000000..ea7eb48 --- /dev/null +++ b/Independent JPEG Group/jpeglib.h @@ -0,0 +1 @@ +/* * jpeglib.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file defines the application interface for the JPEG library. * Most applications using the library need only include this file, * and perhaps jerror.h if they want to know the exact error codes. */ /* * First we include the configuration files that record how this * installation of the JPEG library is set up. jconfig.h can be * generated automatically for many systems. jmorecfg.h contains * manual configuration options that most people need not worry about. */ #ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */ #include "jconfig.h" /* widely used configuration options */ #endif #include "jmorecfg.h" /* seldom changed options */ /* Various constants determining the sizes of things. * All of these are specified by the JPEG standard, so don't change them * if you want to be compatible. */ #define DCTSIZE 8 /* The basic DCT block is 8x8 samples */ #define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */ #define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */ #define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */ #define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */ #define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */ #define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */ #define MAX_BLOCKS_IN_MCU 10 /* JPEG limit on # of blocks in an MCU */ /* This macro is used to declare a "method", that is, a function pointer. * We want to supply prototype parameters if the compiler can cope. * Note that the arglist parameter must be parenthesized! */ #ifdef HAVE_PROTOTYPES #define JMETHOD(type,methodname,arglist) type (*methodname) arglist #else #define JMETHOD(type,methodname,arglist) type (*methodname) () #endif /* Data structures for images (arrays of samples and of DCT coefficients). * On 80x86 machines, the image arrays are too big for near pointers, * but the pointer arrays can fit in near memory. */ typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */ typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */ typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */ typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */ typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */ typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */ typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */ typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */ /* Types for JPEG compression parameters and working tables. */ /* DCT coefficient quantization tables. */ typedef struct { /* This field directly represents the contents of a JPEG DQT marker. * Note: the values are always given in zigzag order. */ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ /* NB: there are additional private fields in an actual quantization data * structure, so don't allocate one directly. Use jpeg_alloc_quant_table. */ } JQUANT_TBL; /* Huffman coding tables. */ typedef struct { /* These two fields directly represent the contents of a JPEG DHT marker */ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */ /* length k bits; bits[0] is unused */ UINT8 huffval[256]; /* The symbols, in order of incr code length */ /* This field is used only during compression. It's initialized FALSE when * the table is created, and set TRUE when it's been output to the file. * You could suppress output of a table by setting this to TRUE. * (See jpeg_suppress_tables for an example.) */ boolean sent_table; /* TRUE when table has been output */ /* NB: there are additional private fields in an actual Huffman-table data * structure, so don't allocate one directly. Use jpeg_alloc_huff_table. */ } JHUFF_TBL; /* Basic info about one component (color channel). */ typedef struct { /* These values are fixed over the whole image. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOF marker. */ int component_id; /* identifier for this component (0..255) */ int component_index; /* its index in SOF or cinfo->comp_info[] */ int h_samp_factor; /* horizontal sampling factor (1..4) */ int v_samp_factor; /* vertical sampling factor (1..4) */ int quant_tbl_no; /* quantization table selector (0..3) */ /* These values may vary between scans. */ /* For compression, they must be supplied by parameter setup; */ /* for decompression, they are read from the SOS marker. */ int dc_tbl_no; /* DC entropy table selector (0..3) */ int ac_tbl_no; /* AC entropy table selector (0..3) */ /* Remaining fields should be treated as private by applications. */ /* These values are computed during compression or decompression startup: */ /* Component's size in DCT blocks. * Any dummy blocks added to complete an MCU are not counted; therefore * these values do not depend on whether a scan is interleaved or not. */ JDIMENSION width_in_blocks; JDIMENSION height_in_blocks; /* Size of a DCT block in samples. Always DCTSIZE for compression. * For decompression this is the size of the output from one DCT block, * reflecting any scaling we choose to apply during the IDCT step. * Values of 1,2,4,8 are likely to be supported. Note that different * components may receive different IDCT scalings. */ int DCT_scaled_size; /* The downsampled dimensions are the component's actual, unpadded number * of samples at the main buffer (preprocessing/compression interface), thus * downsampled_width = ceil(image_width * Hi/Hmax) * and similarly for height. For decompression, IDCT scaling is included, so * downsampled_width = ceil(image_width * Hi/Hmax * DCT_scaled_size/DCTSIZE) */ JDIMENSION downsampled_width; /* actual width in samples */ JDIMENSION downsampled_height; /* actual height in samples */ /* This flag is used only for decompression. In cases where some of the * components will be ignored (eg grayscale output from YCbCr image), * we can skip most computations for the unused components. */ boolean component_needed; /* do we need the value of this component? */ /* These values are computed before starting a scan of the component: */ int MCU_width; /* number of blocks per MCU, horizontally */ int MCU_height; /* number of blocks per MCU, vertically */ int MCU_blocks; /* MCU_width * MCU_height */ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */ int last_col_width; /* # of non-dummy blocks across in last MCU */ int last_row_height; /* # of non-dummy blocks down in last MCU */ } jpeg_component_info; /* Known color spaces. */ typedef enum { JCS_UNKNOWN, /* error/unspecified */ JCS_GRAYSCALE, /* monochrome */ JCS_RGB, /* red/green/blue */ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */ JCS_CMYK, /* C/M/Y/K */ JCS_YCCK /* Y/Cb/Cr/K */ } J_COLOR_SPACE; /* Common fields between JPEG compression and decompression master structs. */ #define jpeg_common_fields \ struct jpeg_error_mgr * err; /* Error handler module */\ struct jpeg_memory_mgr * mem; /* Memory manager module */\ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\ boolean is_decompressor; /* so common code can tell which is which */\ int global_state /* for checking call sequence validity */ /* Routines that are to be used by both halves of the library are declared * to receive a pointer to this structure. There are no actual instances of * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct. */ struct jpeg_common_struct { jpeg_common_fields; /* Fields common to both master struct types */ /* Additional fields follow in an actual jpeg_compress_struct or * jpeg_decompress_struct. All three structs must agree on these * initial fields! (This would be a lot cleaner in C++.) */ }; typedef struct jpeg_common_struct * j_common_ptr; typedef struct jpeg_compress_struct * j_compress_ptr; typedef struct jpeg_decompress_struct * j_decompress_ptr; /* Master record for a compression instance */ struct jpeg_compress_struct { jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */ /* Destination for compressed data */ struct jpeg_destination_mgr * dest; /* Description of source image --- these fields must be filled in by * outer application before starting compression. in_color_space must * be correct before you can even call jpeg_set_defaults(). */ JDIMENSION image_width; /* input image width */ JDIMENSION image_height; /* input image height */ int input_components; /* # of color components in input image */ J_COLOR_SPACE in_color_space; /* colorspace of input image */ double input_gamma; /* image gamma of input image */ /* Compression parameters --- these fields must be set before calling * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to * initialize everything to reasonable defaults, then changing anything * the application specifically wants to change. That way you won't get * burnt when new parameters are added. Also note that there are several * helper routines to simplify changing parameters. */ int data_precision; /* bits of precision in image data */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ boolean interleave; /* TRUE=interleaved output, FALSE=not */ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ int smoothing_factor; /* 1..100, or 0 for no input smoothing */ /* The restart interval can be specified in absolute MCUs by setting * restart_interval, or in MCU rows by setting restart_in_rows * (in which case the correct restart_interval will be figured * for each scan). */ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */ int restart_in_rows; /* if > 0, MCU rows per restart interval */ /* Parameters controlling emission of special markers. */ boolean write_JFIF_header; /* should a JFIF marker be written? */ /* These three values are not used by the JPEG code, merely copied */ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */ /* ratio is defined by X_density/Y_density even when density_unit=0. */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean write_Adobe_marker; /* should an Adobe marker be written? */ /* State variable: index of next scanline to be written to * jpeg_write_scanlines(). Application may use this to control its * processing loop, e.g., "while (next_scanline < image_height)". */ JDIMENSION next_scanline; /* 0 .. image_height-1 */ /* Remaining fields are known throughout compressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during compression startup */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ /* * Links to compression subobjects (methods and private variables of modules) */ struct jpeg_comp_master * master; struct jpeg_c_main_controller * main; struct jpeg_c_prep_controller * prep; struct jpeg_c_coef_controller * coef; struct jpeg_marker_writer * marker; struct jpeg_color_converter * cconvert; struct jpeg_downsampler * downsample; struct jpeg_forward_dct * fdct; struct jpeg_entropy_encoder * entropy; }; /* Master record for a decompression instance */ struct jpeg_decompress_struct { jpeg_common_fields; /* Fields shared with jpeg_compress_struct */ /* Source of compressed data */ struct jpeg_source_mgr * src; /* Basic description of image --- filled in by jpeg_read_header(). */ /* Application may inspect these values to decide how to process image. */ JDIMENSION image_width; /* nominal image width (from SOF marker) */ JDIMENSION image_height; /* nominal image height */ int num_components; /* # of color components in JPEG image */ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */ /* Decompression processing parameters --- these fields must be set before * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes * them to default values. */ J_COLOR_SPACE out_color_space; /* colorspace for output */ unsigned int scale_num, scale_denom; /* fraction by which to scale image */ double output_gamma; /* image gamma wanted in output */ boolean quantize_colors; /* T if output is a colormapped format */ /* the following are ignored if not quantize_colors: */ boolean two_pass_quantize; /* use two-pass color quantization? */ boolean use_dithering; /* want color dithering? */ int desired_number_of_colors; /* max number of colors to use */ boolean do_block_smoothing; /* T = apply cross-block smoothing */ boolean do_fancy_upsampling; /* T = apply fancy upsampling */ /* Description of actual output image that will be returned to application. * These fields are computed by jpeg_start_decompress(). * You can also use jpeg_calc_output_dimensions() to determine these values * in advance of calling jpeg_start_decompress(). */ JDIMENSION output_width; /* scaled image width */ JDIMENSION output_height; /* scaled image height */ int out_color_components; /* # of color components in out_color_space */ int output_components; /* # of color components returned */ /* output_components is 1 (a colormap index) when quantizing colors; * otherwise it equals out_color_components. */ int rec_outbuf_height; /* min recommended height of scanline buffer */ /* If the buffer passed to jpeg_read_scanlines() is less than this many rows * high, space and time will be wasted due to unnecessary data copying. * Usually rec_outbuf_height will be 1 or 2, at most 4. */ /* When quantizing colors, the output colormap is described by these fields. * The application can supply a colormap by setting colormap non-NULL before * calling jpeg_start_decompress; otherwise a colormap is created during * jpeg_start_decompress. * The map has out_color_components rows and actual_number_of_colors columns. */ int actual_number_of_colors; /* number of entries in use */ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */ /* State variable: index of next scaled scanline to be read from * jpeg_read_scanlines(). Application may use this to control its * processing loop, e.g., "while (output_scanline < output_height)". */ JDIMENSION output_scanline; /* 0 .. output_height-1 */ /* Internal JPEG parameters --- the application usually need not look at * these fields. */ /* Quantization and Huffman tables are carried forward across input * datastreams when processing abbreviated JPEG datastreams. */ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]; /* ptrs to coefficient quantization tables, or NULL if not defined */ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]; JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]; /* ptrs to Huffman coding tables, or NULL if not defined */ /* These parameters are never carried across datastreams, since they * are given in SOF/SOS markers or defined to be reset by SOI. */ int data_precision; /* bits of precision in image data */ jpeg_component_info * comp_info; /* comp_info[i] describes component that appears i'th in SOF */ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */ unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */ /* These fields record data obtained from optional markers recognized by * the JPEG library. */ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */ /* Data copied from JFIF marker: */ UINT8 density_unit; /* JFIF code for pixel size units */ UINT16 X_density; /* Horizontal pixel density */ UINT16 Y_density; /* Vertical pixel density */ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */ UINT8 Adobe_transform; /* Color transform code from Adobe marker */ boolean CCIR601_sampling; /* TRUE=first samples are cosited */ /* Remaining fields are known throughout decompressor, but generally * should not be touched by a surrounding application. */ /* * These fields are computed during decompression startup */ int max_h_samp_factor; /* largest h_samp_factor */ int max_v_samp_factor; /* largest v_samp_factor */ int min_DCT_scaled_size; /* smallest DCT_scaled_size of any component */ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be output by coef ctlr */ /* The coefficient controller outputs data in units of MCU rows as defined * for fully interleaved scans (whether the JPEG file is interleaved or not). * There are v_samp_factor * DCT_scaled_size sample rows of each component * in an "iMCU" (interleaved MCU) row. */ JSAMPLE * sample_range_limit; /* table for fast range-limiting */ /* * These fields are valid during any one scan. * They describe the components and MCUs actually appearing in the scan. */ int comps_in_scan; /* # of JPEG components in this scan */ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN]; /* *cur_comp_info[i] describes component that appears i'th in SOS */ JDIMENSION MCUs_per_row; /* # of MCUs across the image */ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */ int blocks_in_MCU; /* # of DCT blocks per MCU */ int MCU_membership[MAX_BLOCKS_IN_MCU]; /* MCU_membership[i] is index in cur_comp_info of component owning */ /* i'th block in an MCU */ /* This field is shared between entropy decoder and marker parser. * It is either zero or the code of a JPEG marker that has been * read from the data source, but has not yet been processed. */ int unread_marker; /* * Links to decompression subobjects (methods, private variables of modules) */ struct jpeg_decomp_master * master; struct jpeg_d_main_controller * main; struct jpeg_d_coef_controller * coef; struct jpeg_d_post_controller * post; struct jpeg_marker_reader * marker; struct jpeg_entropy_decoder * entropy; struct jpeg_inverse_dct * idct; struct jpeg_upsampler * upsample; struct jpeg_color_deconverter * cconvert; struct jpeg_color_quantizer * cquantize; }; /* "Object" declarations for JPEG modules that may be supplied or called * directly by the surrounding application. * As with all objects in the JPEG library, these structs only define the * publicly visible methods and state variables of a module. Additional * private fields may exist after the public ones. */ /* Error handler object */ struct jpeg_error_mgr { /* Error exit handler: does not return to caller */ JMETHOD(void, error_exit, (j_common_ptr cinfo)); /* Conditionally emit a trace or warning message */ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level)); /* Routine that actually outputs a trace or error message */ JMETHOD(void, output_message, (j_common_ptr cinfo)); /* Format a message string for the most recent JPEG error or message */ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer)); #define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */ /* Reset error state variables at start of a new image */ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo)); /* The message ID code and any parameters are saved here. * A message can have one string parameter or up to 8 int parameters. */ int msg_code; #define JMSG_STR_PARM_MAX 80 union { int i[8]; char s[JMSG_STR_PARM_MAX]; } msg_parm; /* Standard state variables for error facility */ int trace_level; /* max msg_level that will be displayed */ /* For recoverable corrupt-data errors, we emit a warning message, * but keep going unless emit_message chooses to abort. emit_message * should count warnings in num_warnings. The surrounding application * can check for bad data by seeing if num_warnings is nonzero at the * end of processing. */ long num_warnings; /* number of corrupt-data warnings */ /* These fields point to the table(s) of error message strings. * An application can change the table pointer to switch to a different * message list (typically, to change the language in which errors are * reported). Some applications may wish to add additional error codes * that will be handled by the JPEG library error mechanism; the second * table pointer is used for this purpose. * * First table includes all errors generated by JPEG library itself. * Error code 0 is reserved for a "no such error string" message. */ const char * const * jpeg_message_table; /* Library errors */ int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */ /* Second table can be added by application (see cjpeg/djpeg for example). * It contains strings numbered first_addon_message..last_addon_message. */ const char * const * addon_message_table; /* Non-library errors */ int first_addon_message; /* code for first string in addon table */ int last_addon_message; /* code for last string in addon table */ }; /* Progress monitor object */ struct jpeg_progress_mgr { JMETHOD(void, progress_monitor, (j_common_ptr cinfo)); long pass_counter; /* work units completed in this pass */ long pass_limit; /* total number of work units in this pass */ int completed_passes; /* passes completed so far */ int total_passes; /* total number of passes expected */ }; /* Data destination object for compression */ struct jpeg_destination_mgr { JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ JMETHOD(void, init_destination, (j_compress_ptr cinfo)); JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo)); JMETHOD(void, term_destination, (j_compress_ptr cinfo)); }; /* Data source object for decompression */ struct jpeg_source_mgr { const JOCTET * next_input_byte; /* => next byte to read from buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */ JMETHOD(void, init_source, (j_decompress_ptr cinfo)); JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo)); JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes)); JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo)); JMETHOD(void, term_source, (j_decompress_ptr cinfo)); }; /* Memory manager object. * Allocates "small" objects (a few K total), "large" objects (tens of K), * and "really big" objects (virtual arrays with backing store if needed). * The memory manager does not allow individual objects to be freed; rather, * each created object is assigned to a pool, and whole pools can be freed * at once. This is faster and more convenient than remembering exactly what * to free, especially where malloc()/free() are not too speedy. * NB: alloc routines never return NULL. They exit to error_exit if not * successful. */ #define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */ #define JPOOL_IMAGE 1 /* lasts until done with image/datastream */ #define JPOOL_NUMPOOLS 2 typedef struct jvirt_sarray_control * jvirt_sarray_ptr; typedef struct jvirt_barray_control * jvirt_barray_ptr; struct jpeg_memory_mgr { /* Method pointers */ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id, size_t sizeofobject)); JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows)); JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows)); JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows, JDIMENSION unitheight)); JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo, int pool_id, JDIMENSION blocksperrow, JDIMENSION numrows, JDIMENSION unitheight)); JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo)); JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo, jvirt_sarray_ptr ptr, JDIMENSION start_row, boolean writable)); JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo, jvirt_barray_ptr ptr, JDIMENSION start_row, boolean writable)); JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id)); JMETHOD(void, self_destruct, (j_common_ptr cinfo)); /* Limit on memory allocation for this JPEG object. (Note that this is * merely advisory, not a guaranteed maximum; it only affects the space * used for virtual-array buffers.) May be changed by outer application * after creating the JPEG object. */ long max_memory_to_use; }; /* Declarations for routines called by application. * The JPP macro hides prototype parameters from compilers that can't cope. * Note JPP requires double parentheses. */ #ifdef HAVE_PROTOTYPES #define JPP(arglist) arglist #else #define JPP(arglist) () #endif /* Short forms of external names for systems with brain-damaged linkers. * We shorten external names to be unique in the first six letters, which * is good enough for all known systems. * (If your compiler itself needs names to be unique in less than 15 * characters, you are out of luck. Get a better compiler.) */ #ifdef NEED_SHORT_EXTERNAL_NAMES #define jpeg_std_error jStdError #define jpeg_create_compress jCreaCompress #define jpeg_create_decompress jCreaDecompress #define jpeg_destroy_compress jDestCompress #define jpeg_destroy_decompress jDestDecompress #define jpeg_stdio_dest jStdDest #define jpeg_stdio_src jStdSrc #define jpeg_set_defaults jSetDefaults #define jpeg_set_colorspace jSetColorspace #define jpeg_set_quality jSetQuality #define jpeg_set_linear_quality jSetLQuality #define jpeg_add_quant_table jAddQuantTable #define jpeg_quality_scaling jQualityScaling #define jpeg_suppress_tables jSuppressTables #define jpeg_alloc_quant_table jAlcQTable #define jpeg_alloc_huff_table jAlcHTable #define jpeg_start_compress jStrtCompress #define jpeg_write_scanlines jWrtScanlines #define jpeg_finish_compress jFinCompress #define jpeg_write_tables jWrtTables #define jpeg_read_header jReadHeader #define jpeg_start_decompress jStrtDecompress #define jpeg_read_scanlines jReadScanlines #define jpeg_finish_decompress jFinDecompress #define jpeg_calc_output_dimensions jCalcDimensions #define jpeg_abort_compress jAbrtCompress #define jpeg_abort_decompress jAbrtDecompress #define jpeg_abort jAbort #define jpeg_destroy jDestroy #define jpeg_resync_to_restart jResyncRestart #endif /* NEED_SHORT_EXTERNAL_NAMES */ /* Default error-management setup */ EXTERN struct jpeg_error_mgr *jpeg_std_error JPP((struct jpeg_error_mgr *err)); /* Initialization and destruction of JPEG compression objects */ /* NB: you must set up the error-manager BEFORE calling jpeg_create_xxx */ EXTERN void jpeg_create_compress JPP((j_compress_ptr cinfo)); EXTERN void jpeg_create_decompress JPP((j_decompress_ptr cinfo)); EXTERN void jpeg_destroy_compress JPP((j_compress_ptr cinfo)); EXTERN void jpeg_destroy_decompress JPP((j_decompress_ptr cinfo)); /* Standard data source and destination managers: stdio streams. */ /* Caller is responsible for opening the file before and closing after. */ EXTERN void jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile)); EXTERN void jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile)); /* Default parameter setup for compression */ EXTERN void jpeg_set_defaults JPP((j_compress_ptr cinfo)); /* Compression parameter setup aids */ EXTERN void jpeg_set_colorspace JPP((j_compress_ptr cinfo, J_COLOR_SPACE colorspace)); EXTERN void jpeg_set_quality JPP((j_compress_ptr cinfo, int quality, boolean force_baseline)); EXTERN void jpeg_set_linear_quality JPP((j_compress_ptr cinfo, int scale_factor, boolean force_baseline)); EXTERN void jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline)); EXTERN int jpeg_quality_scaling JPP((int quality)); EXTERN void jpeg_suppress_tables JPP((j_compress_ptr cinfo, boolean suppress)); EXTERN JQUANT_TBL * jpeg_alloc_quant_table JPP((j_common_ptr cinfo)); EXTERN JHUFF_TBL * jpeg_alloc_huff_table JPP((j_common_ptr cinfo)); /* Main entry points for compression */ EXTERN void jpeg_start_compress JPP((j_compress_ptr cinfo, boolean write_all_tables)); EXTERN JDIMENSION jpeg_write_scanlines JPP((j_compress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION num_lines)); EXTERN void jpeg_finish_compress JPP((j_compress_ptr cinfo)); /* Alternate compression function: just write an abbreviated table file */ EXTERN void jpeg_write_tables JPP((j_compress_ptr cinfo)); /* Decompression startup: read start of JPEG datastream to see what's there */ EXTERN int jpeg_read_header JPP((j_decompress_ptr cinfo, boolean require_image)); /* Return value is one of: */ #define JPEG_HEADER_OK 0 /* Found valid image datastream */ #define JPEG_HEADER_TABLES_ONLY 1 /* Found valid table-specs-only datastream */ #define JPEG_SUSPENDED 2 /* Had to suspend before end of headers */ /* If you pass require_image = TRUE (normal case), you need not check for * a TABLES_ONLY return code; an abbreviated file will cause an error exit. * JPEG_SUSPENDED is only possible if you use a data source module that can * give a suspension return (the stdio source module doesn't). */ /* Main entry points for decompression */ EXTERN void jpeg_start_decompress JPP((j_decompress_ptr cinfo)); EXTERN JDIMENSION jpeg_read_scanlines JPP((j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines)); EXTERN boolean jpeg_finish_decompress JPP((j_decompress_ptr cinfo)); /* Precalculate output dimensions for current decompression parameters. */ EXTERN void jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo)); /* If you choose to abort compression or decompression before completing * jpeg_finish_(de)compress, then you need to clean up to release memory, * temporary files, etc. You can just call jpeg_destroy_(de)compress * if you're done with the JPEG object, but if you want to clean it up and * reuse it, call this: */ EXTERN void jpeg_abort_compress JPP((j_compress_ptr cinfo)); EXTERN void jpeg_abort_decompress JPP((j_decompress_ptr cinfo)); /* Generic versions of jpeg_abort and jpeg_destroy that work on either * flavor of JPEG object. These may be more convenient in some places. */ EXTERN void jpeg_abort JPP((j_common_ptr cinfo)); EXTERN void jpeg_destroy JPP((j_common_ptr cinfo)); /* Default restart-marker-resync procedure for use by data source modules */ EXTERN boolean jpeg_resync_to_restart JPP((j_decompress_ptr cinfo)); /* These marker codes are exported since applications and data source modules * are likely to want to use them. */ #define JPEG_RST0 0xD0 /* RST0 marker code */ #define JPEG_EOI 0xD9 /* EOI marker code */ #define JPEG_APP0 0xE0 /* APP0 marker code */ #define JPEG_COM 0xFE /* COM marker code */ /* If we have a brain-damaged compiler that emits warnings (or worse, errors) * for structure definitions that are never filled in, keep it quiet by * supplying dummy definitions for the various substructures. */ #ifdef INCOMPLETE_TYPES_BROKEN #ifndef JPEG_INTERNALS /* will be defined in jpegint.h */ struct jvirt_sarray_control { long dummy; }; struct jvirt_barray_control { long dummy; }; struct jpeg_comp_master { long dummy; }; struct jpeg_c_main_controller { long dummy; }; struct jpeg_c_prep_controller { long dummy; }; struct jpeg_c_coef_controller { long dummy; }; struct jpeg_marker_writer { long dummy; }; struct jpeg_color_converter { long dummy; }; struct jpeg_downsampler { long dummy; }; struct jpeg_forward_dct { long dummy; }; struct jpeg_entropy_encoder { long dummy; }; struct jpeg_decomp_master { long dummy; }; struct jpeg_d_main_controller { long dummy; }; struct jpeg_d_coef_controller { long dummy; }; struct jpeg_d_post_controller { long dummy; }; struct jpeg_marker_reader { long dummy; }; struct jpeg_entropy_decoder { long dummy; }; struct jpeg_inverse_dct { long dummy; }; struct jpeg_upsampler { long dummy; }; struct jpeg_color_deconverter { long dummy; }; struct jpeg_color_quantizer { long dummy; }; #endif /* JPEG_INTERNALS */ #endif /* INCOMPLETE_TYPES_BROKEN */ /* * The JPEG library modules define JPEG_INTERNALS before including this file. * The internal structure declarations are read only when that is true. * Applications using the library should not include jpegint.h, but may wish * to include jerror.h. */ #ifdef JPEG_INTERNALS #include "jpegint.h" /* fetch private declarations */ #include "jerror.h" /* fetch error codes too */ #endif \ No newline at end of file diff --git a/Independent JPEG Group/jquant1.c b/Independent JPEG Group/jquant1.c new file mode 100644 index 0000000..3e8bb0a --- /dev/null +++ b/Independent JPEG Group/jquant1.c @@ -0,0 +1 @@ +/* * jquant1.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 1-pass color quantization (color mapping) routines. * These routines provide mapping to a fixed color map using equally spaced * color values. Optional Floyd-Steinberg dithering is available. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef QUANT_1PASS_SUPPORTED /* * The main purpose of 1-pass quantization is to provide a fast, if not very * high quality, colormapped output capability. A 2-pass quantizer usually * gives better visual quality; however, for quantized grayscale output this * quantizer is perfectly adequate. Dithering is highly recommended with this * quantizer, though you can turn it off if you really want to. * * In 1-pass quantization the colormap must be chosen in advance of seeing the * image. We use a map consisting of all combinations of Ncolors[i] color * values for the i'th component. The Ncolors[] values are chosen so that * their product, the total number of colors, is no more than that requested. * (In most cases, the product will be somewhat less.) * * Since the colormap is orthogonal, the representative value for each color * component can be determined without considering the other components; * then these indexes can be combined into a colormap index by a standard * N-dimensional-array-subscript calculation. Most of the arithmetic involved * can be precalculated and stored in the lookup table colorindex[]. * colorindex[i][j] maps pixel value j in component i to the nearest * representative value (grid plane) for that component; this index is * multiplied by the array stride for component i, so that the * index of the colormap entry closest to a given pixel value is just * sum( colorindex[component-number][pixel-component-value] ) * Aside from being fast, this scheme allows for variable spacing between * representative values with no additional lookup cost. * * If gamma correction has been applied in color conversion, it might be wise * to adjust the color grid spacing so that the representative colors are * equidistant in linear space. At this writing, gamma correction is not * implemented by jdcolor, so nothing is done here. */ /* Declarations for Floyd-Steinberg dithering. * * Errors are accumulated into the array fserrors[], at a resolution of * 1/16th of a pixel count. The error at a given pixel is propagated * to its not-yet-processed neighbors using the standard F-S fractions, * ... (here) 7/16 * 3/16 5/16 1/16 * We work left-to-right on even rows, right-to-left on odd rows. * * We can get away with a single array (holding one row's worth of errors) * by using it to store the current row's errors at pixel columns not yet * processed, but the next row's errors at columns already processed. We * need only a few extra variables to hold the errors immediately around the * current column. (If we are lucky, those variables are in registers, but * even if not, they're probably cheaper to access than array elements are.) * * The fserrors[] array is indexed [component#][position]. * We provide (#columns + 2) entries per component; the extra entry at each * end saves us from special-casing the first and last pixels. * * Note: on a wide image, we might not have enough room in a PC's near data * segment to hold the error array; so it is allocated with alloc_large. */ #if BITS_IN_JSAMPLE == 8 typedef INT16 FSERROR; /* 16 bits should be enough */ typedef int LOCFSERROR; /* use 'int' for calculation temps */ #else typedef INT32 FSERROR; /* may need more than 16 bits */ typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */ #endif typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */ /* Private subobject */ #define MAX_Q_COMPS 4 /* max components I can handle */ typedef struct { struct jpeg_color_quantizer pub; /* public fields */ JSAMPARRAY colorindex; /* Precomputed mapping for speed */ /* colorindex[i][j] = index of color closest to pixel value j in component i, * premultiplied as described above. Since colormap indexes must fit into * JSAMPLEs, the entries of this array will too. */ /* Variables for Floyd-Steinberg dithering */ FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */ boolean on_odd_row; /* flag to remember which row we are on */ } my_cquantizer; typedef my_cquantizer * my_cquantize_ptr; /* * Policy-making subroutines for create_colormap: these routines determine * the colormap to be used. The rest of the module only assumes that the * colormap is orthogonal. * * * select_ncolors decides how to divvy up the available colors * among the components. * * output_value defines the set of representative values for a component. * * largest_input_value defines the mapping from input values to * representative values for a component. * Note that the latter two routines may impose different policies for * different components, though this is not currently done. */ LOCAL int select_ncolors (j_decompress_ptr cinfo, int Ncolors[]) /* Determine allocation of desired colors to components, */ /* and fill in Ncolors[] array to indicate choice. */ /* Return value is total number of colors (product of Ncolors[] values). */ { int nc = cinfo->out_color_components; /* number of color components */ int max_colors = cinfo->desired_number_of_colors; int total_colors, iroot, i; long temp; boolean changed; /* We can allocate at least the nc'th root of max_colors per component. */ /* Compute floor(nc'th root of max_colors). */ iroot = 1; do { iroot++; temp = iroot; /* set temp = iroot ** nc */ for (i = 1; i < nc; i++) temp *= iroot; } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */ iroot--; /* now iroot = floor(root) */ /* Must have at least 2 color values per component */ if (iroot < 2) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp); if (cinfo->out_color_space == JCS_RGB && nc == 3) { /* We provide a special policy for quantizing in RGB space. * If 256 colors are requested, we allocate 8 red, 8 green, 4 blue levels; * this corresponds to the common 3/3/2-bit scheme. For other totals, * the counts are set so that the number of colors allocated to each * component are roughly in the proportion R 3, G 4, B 2. * For low color counts, it's easier to hardwire the optimal choices * than try to tweak the algorithm to generate them. */ if (max_colors == 256) { Ncolors[0] = 8; Ncolors[1] = 8; Ncolors[2] = 4; return 256; } if (max_colors < 12) { /* Fixed mapping for 8 colors */ Ncolors[0] = Ncolors[1] = Ncolors[2] = 2; } else if (max_colors < 18) { /* Fixed mapping for 12 colors */ Ncolors[0] = 2; Ncolors[1] = 3; Ncolors[2] = 2; } else if (max_colors < 24) { /* Fixed mapping for 18 colors */ Ncolors[0] = 3; Ncolors[1] = 3; Ncolors[2] = 2; } else if (max_colors < 27) { /* Fixed mapping for 24 colors */ Ncolors[0] = 3; Ncolors[1] = 4; Ncolors[2] = 2; } else if (max_colors < 36) { /* Fixed mapping for 27 colors */ Ncolors[0] = 3; Ncolors[1] = 3; Ncolors[2] = 3; } else { /* these weights are readily derived with a little algebra */ Ncolors[0] = (iroot * 266) >> 8; /* R weight is 1.0400 */ Ncolors[1] = (iroot * 355) >> 8; /* G weight is 1.3867 */ Ncolors[2] = (iroot * 177) >> 8; /* B weight is 0.6934 */ } total_colors = Ncolors[0] * Ncolors[1] * Ncolors[2]; /* The above computation produces "floor" values, so we may be able to * increment the count for one or more components without exceeding * max_colors. We try in the order B, G, R. */ do { changed = FALSE; for (i = 2; i >= 0; i--) { /* calculate new total_colors if Ncolors[i] is incremented */ temp = total_colors / Ncolors[i]; temp *= Ncolors[i]+1; /* done in long arith to avoid oflo */ if (temp <= (long) max_colors) { Ncolors[i]++; /* OK, apply the increment */ total_colors = (int) temp; changed = TRUE; } } } while (changed); /* loop until no increment is possible */ } else { /* For any colorspace besides RGB, treat all the components equally. */ /* Initialize to iroot color values for each component */ total_colors = 1; for (i = 0; i < nc; i++) { Ncolors[i] = iroot; total_colors *= iroot; } /* We may be able to increment the count for one or more components without * exceeding max_colors, though we know not all can be incremented. */ for (i = 0; i < nc; i++) { /* calculate new total_colors if Ncolors[i] is incremented */ temp = total_colors / Ncolors[i]; temp *= Ncolors[i]+1; /* done in long arith to avoid oflo */ if (temp > (long) max_colors) break; /* won't fit, done */ Ncolors[i]++; /* OK, apply the increment */ total_colors = (int) temp; } } return total_colors; } LOCAL int output_value (j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return j'th output value, where j will range from 0 to maxj */ /* The output values must fall in 0..MAXJSAMPLE in increasing order */ { /* We always provide values 0 and MAXJSAMPLE for each component; * any additional values are equally spaced between these limits. * (Forcing the upper and lower values to the limits ensures that * dithering can't produce a color outside the selected gamut.) */ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj); } LOCAL int largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj) /* Return largest input value that should map to j'th output value */ /* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */ { /* Breakpoints are halfway between values returned by output_value */ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj)); } /* * Create the colormap and color index table. */ LOCAL void create_colormap (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPARRAY colormap; /* Created colormap */ int total_colors; /* Number of distinct output colors */ int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */ int i,j,k, nci, blksize, blkdist, ptr, val; /* Select number of colors for each component */ total_colors = select_ncolors(cinfo, Ncolors); /* Report selected color counts */ if (cinfo->out_color_components == 3) TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS, total_colors, Ncolors[0], Ncolors[1], Ncolors[2]); else TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors); /* Allocate and fill in the colormap and color index. */ /* The colors are ordered in the map in standard row-major order, */ /* i.e. rightmost (highest-indexed) color changes most rapidly. */ colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components); cquantize->colorindex = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) cinfo->out_color_components); /* blksize is number of adjacent repeated entries for a component */ /* blkdist is distance between groups of identical entries for a component */ blkdist = total_colors; for (i = 0; i < cinfo->out_color_components; i++) { /* fill in colormap entries for i'th color component */ nci = Ncolors[i]; /* # of distinct values for this color */ blksize = blkdist / nci; for (j = 0; j < nci; j++) { /* Compute j'th output value (out of nci) for component */ val = output_value(cinfo, i, j, nci-1); /* Fill in all colormap entries that have this value of this component */ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) { /* fill in blksize entries beginning at ptr */ for (k = 0; k < blksize; k++) colormap[i][ptr+k] = (JSAMPLE) val; } } blkdist = blksize; /* blksize of this color is blkdist of next */ /* fill in colorindex entries for i'th color component */ /* in loop, val = index of current output value, */ /* and k = largest j that maps to current val */ val = 0; k = largest_input_value(cinfo, i, 0, nci-1); for (j = 0; j <= MAXJSAMPLE; j++) { while (j > k) /* advance val if past boundary */ k = largest_input_value(cinfo, i, ++val, nci-1); /* premultiply so that no multiplication needed in main processing */ cquantize->colorindex[i][j] = (JSAMPLE) (val * blksize); } } /* Make the colormap available to the application. */ cinfo->colormap = colormap; cinfo->actual_number_of_colors = total_colors; } /* * Map some rows of pixels to the output colormapped representation. */ METHODDEF void color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; JSAMPARRAY colorindex = cquantize->colorindex; register int pixcode, ci; register JSAMPROW ptrin, ptrout; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; register int nc = cinfo->out_color_components; for (row = 0; row < num_rows; row++) { ptrin = input_buf[row]; ptrout = output_buf[row]; for (col = width; col > 0; col--) { pixcode = 0; for (ci = 0; ci < nc; ci++) { pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]); } *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF void color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* Fast path for out_color_components==3, no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register int pixcode; register JSAMPROW ptrin, ptrout; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPROW colorindex0 = cquantize->colorindex[0]; JSAMPROW colorindex1 = cquantize->colorindex[1]; JSAMPROW colorindex2 = cquantize->colorindex[2]; for (row = 0; row < num_rows; row++) { ptrin = input_buf[row]; ptrout = output_buf[row]; for (col = width; col > 0; col--) { pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]); pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]); pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]); *ptrout++ = (JSAMPLE) pixcode; } } } METHODDEF void color_quantize_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* General case, with Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; register LOCFSERROR cur; /* current error or pixel value */ LOCFSERROR belowerr; /* error for pixel below cur */ LOCFSERROR bpreverr; /* error for below/prev col */ LOCFSERROR bnexterr; /* error for below/next col */ LOCFSERROR delta; register FSERRPTR errorptr; /* => fserrors[] at column before current */ register JSAMPROW input_ptr; register JSAMPROW output_ptr; JSAMPROW colorindex_ci; JSAMPROW colormap_ci; int pixcode; int nc = cinfo->out_color_components; int dir; /* 1 for left-to-right, -1 for right-to-left */ int dirnc; /* dir * nc */ int ci; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPLE *range_limit = cinfo->sample_range_limit; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { /* Initialize output values to 0 so can process components separately */ jzero_far((void FAR *) output_buf[row], (size_t) (width * SIZEOF(JSAMPLE))); for (ci = 0; ci < nc; ci++) { input_ptr = input_buf[row] + ci; output_ptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ input_ptr += (width-1) * nc; /* so point to rightmost pixel */ output_ptr += width-1; dir = -1; dirnc = -nc; errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */ } else { /* work left to right in this row */ dir = 1; dirnc = nc; errorptr = cquantize->fserrors[ci]; /* => entry before first column */ } colorindex_ci = cquantize->colorindex[ci]; colormap_ci = cinfo->colormap[ci]; /* Preset error values: no error propagated to first pixel from left */ cur = 0; /* and no error propagated to row below yet */ belowerr = bpreverr = 0; for (col = width; col > 0; col--) { /* cur holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4); /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE; this sets the required size * of the range_limit array. */ cur += GETJSAMPLE(*input_ptr); cur = GETJSAMPLE(range_limit[cur]); /* Select output value, accumulate into output code for this pixel */ pixcode = GETJSAMPLE(colorindex_ci[cur]); *output_ptr += (JSAMPLE) pixcode; /* Compute actual representation error at this pixel */ /* Note: we can do this even though we don't have the final */ /* pixel code, because the colormap is orthogonal. */ cur -= GETJSAMPLE(colormap_ci[pixcode]); /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ bnexterr = cur; delta = cur * 2; cur += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr + cur); cur += delta; /* form error * 5 */ bpreverr = belowerr + cur; belowerr = bnexterr; cur += delta; /* form error * 7 */ /* At this point cur contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ input_ptr += dirnc; /* advance input ptr to next column */ output_ptr += dir; /* advance output ptr to next column */ errorptr += dir; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error value into the * final fserrors[] entry. Note we need not unload belowerr because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */ } cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE); } } /* * Initialize for one-pass color quantization. */ METHODDEF void start_pass (j_decompress_ptr cinfo, boolean is_pre_scan) { /* no work in 1-pass case */ } /* * Finish up at the end of the pass. */ METHODDEF void finish_pass (j_decompress_ptr cinfo) { /* no work in 1-pass case */ } /* * Module initialization routine for 1-pass color quantization. */ GLOBAL void jinit_1pass_quantizer (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; int i; cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass; cquantize->pub.finish_pass = finish_pass; if (cinfo->use_dithering) cquantize->pub.color_quantize = color_quantize_dither; else if (cinfo->out_color_components == 3) cquantize->pub.color_quantize = color_quantize3; else cquantize->pub.color_quantize = color_quantize; /* Make sure my internal arrays won't overflow */ if (cinfo->out_color_components > MAX_Q_COMPS) ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1)) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1); /* Create the colormap. */ create_colormap(cinfo); /* Allocate Floyd-Steinberg workspace if necessary. */ /* We do this now since it is FAR storage and may affect the memory */ /* manager's space calculations. */ if (cinfo->use_dithering) { size_t arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR)); for (i = 0; i < cinfo->out_color_components; i++) { cquantize->fserrors[i] = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); /* Initialize the propagated errors to zero. */ jzero_far((void FAR *) cquantize->fserrors[i], arraysize); } cquantize->on_odd_row = FALSE; } } #endif /* QUANT_1PASS_SUPPORTED */ \ No newline at end of file diff --git a/Independent JPEG Group/jquant2.c b/Independent JPEG Group/jquant2.c new file mode 100644 index 0000000..39080d9 --- /dev/null +++ b/Independent JPEG Group/jquant2.c @@ -0,0 +1 @@ +/* * jquant2.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains 2-pass color quantization (color mapping) routines. * These routines provide selection of a custom color map for an image, * followed by mapping of the image to that color map (with optional * Floyd-Steinberg dithering). * It is also possible to use just the second pass to map to an arbitrary * externally-given color map. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" #ifdef QUANT_2PASS_SUPPORTED /* * This module implements the well-known Heckbert paradigm for color * quantization. Most of the ideas used here can be traced back to * Heckbert's seminal paper * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display", * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304. * * In the first pass over the image, we accumulate a histogram showing the * usage count of each possible color. To keep the histogram to a reasonable * size, we reduce the precision of the input; typical practice is to retain * 5 or 6 bits per color, so that 8 or 4 different input values are counted * in the same histogram cell. * * Next, the color-selection step begins with a box representing the whole * color space, and repeatedly splits the "largest" remaining box until we * have as many boxes as desired colors. Then the mean color in each * remaining box becomes one of the possible output colors. * * The second pass over the image maps each input pixel to the closest output * color (optionally after applying a Floyd-Steinberg dithering correction). * This mapping is logically trivial, but making it go fast enough requires * considerable care. * * Heckbert-style quantizers vary a good deal in their policies for choosing * the "largest" box and deciding where to cut it. The particular policies * used here have proved out well in experimental comparisons, but better ones * may yet be found. * * In earlier versions of the IJG code, this module quantized in YCbCr color * space, processing the raw upsampled data without a color conversion step. * This allowed the color conversion math to be done only once per colormap * entry, not once per pixel. However, that optimization precluded other * useful optimizations (such as merging color conversion with upsampling) * and it also interfered with desired capabilities such as quantizing to an * externally-supplied colormap. We have therefore abandoned that approach. * The present code works in the post-conversion color space, typically RGB. */ #define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */ /* * First we have the histogram data structure and routines for creating it. * * The number of bits of precision can be adjusted by changing these symbols. * We recommend keeping 6 bits for G and 5 each for R and B. * If you have plenty of memory and cycles, 6 bits all around gives marginally * better results; if you are short of memory, 5 bits all around will save * some space but degrade the results. * To maintain a fully accurate histogram, we'd need to allocate a "long" * (preferably unsigned long) for each cell. In practice this is overkill; * we can get by with 16 bits per cell. Few of the cell counts will overflow, * and clamping those that do overflow to the maximum value will give close- * enough results. This reduces the recommended histogram size from 256Kb * to 128Kb, which is a useful savings on PC-class machines. * (In the second pass the histogram space is re-used for pixel mapping data; * in that capacity, each cell must be able to store zero to the number of * desired colors. 16 bits/cell is plenty for that too.) * Since the JPEG code is intended to run in small memory model on 80x86 * machines, we can't just allocate the histogram in one chunk. Instead * of a true 3-D array, we use a row of pointers to 2-D arrays. Each * pointer corresponds to an R value (typically 2^5 = 32 pointers) and * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that * on 80x86 machines, the pointer row is in near memory but the actual * arrays are in far memory (same arrangement as we use for image arrays). */ #define HIST_R_BITS 5 /* bits of precision in R histogram */ #define HIST_G_BITS 6 /* bits of precision in G histogram */ #define HIST_B_BITS 5 /* bits of precision in B histogram */ /* Number of elements along histogram axes. */ #define HIST_R_ELEMS (1<cquantize; register JSAMPROW ptr; register histptr histp; register hist3d histogram = cquantize->histogram; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { ptr = input_buf[row]; for (col = width; col > 0; col--) { /* get pixel value and index into the histogram */ histp = & histogram[GETJSAMPLE(ptr[0]) >> R_SHIFT] [GETJSAMPLE(ptr[1]) >> G_SHIFT] [GETJSAMPLE(ptr[2]) >> B_SHIFT]; /* increment, check for overflow and undo increment if so. */ if (++(*histp) <= 0) (*histp)--; ptr += 3; } } } /* * Next we have the really interesting routines: selection of a colormap * given the completed histogram. * These routines work with a list of "boxes", each representing a rectangular * subset of the input color space (to histogram precision). */ typedef struct { /* The bounds of the box (inclusive); expressed as histogram indexes */ int c0min, c0max; int c1min, c1max; int c2min, c2max; /* The volume (actually 2-norm) of the box */ unsigned int volume; /* The number of nonzero histogram cells within this box */ long colorcount; } box; typedef box * boxptr; LOCAL boxptr find_biggest_color_pop (boxptr boxlist, int numboxes) /* Find the splittable box with the largest color population */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register long max = 0; boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->colorcount > max && boxp->volume > 0) { which = boxp; max = boxp->colorcount; } } return which; } LOCAL boxptr find_biggest_volume (boxptr boxlist, int numboxes) /* Find the splittable box with the largest (scaled) volume */ /* Returns NULL if no splittable boxes remain */ { register boxptr boxp; register int i; register unsigned int max = 0; boxptr which = NULL; for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { if (boxp->volume > max) { which = boxp; max = boxp->volume; } } return which; } LOCAL void update_box (j_decompress_ptr cinfo, boxptr boxp) /* Shrink the min/max bounds of a box to enclose only nonzero elements, */ /* and recompute its volume and population */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; long ccount; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0min = c0min = c0; goto have_c0min; } } have_c0min: if (c0max > c0min) for (c0 = c0max; c0 >= c0min; c0--) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c0max = c0max = c0; goto have_c0max; } } have_c0max: if (c1max > c1min) for (c1 = c1min; c1 <= c1max; c1++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1min = c1min = c1; goto have_c1min; } } have_c1min: if (c1max > c1min) for (c1 = c1max; c1 >= c1min; c1--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) if (*histp++ != 0) { boxp->c1max = c1max = c1; goto have_c1max; } } have_c1max: if (c2max > c2min) for (c2 = c2min; c2 <= c2max; c2++) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_B_ELEMS) if (*histp != 0) { boxp->c2min = c2min = c2; goto have_c2min; } } have_c2min: if (c2max > c2min) for (c2 = c2max; c2 >= c2min; c2--) for (c0 = c0min; c0 <= c0max; c0++) { histp = & histogram[c0][c1min][c2]; for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_B_ELEMS) if (*histp != 0) { boxp->c2max = c2max = c2; goto have_c2max; } } have_c2max: /* Update box volume. * We use 2-norm rather than real volume here; this has the advantage * that a box is splittable iff norm > 0. * Some care is needed since the differences are expressed in * histogram-cell units; if the HIST_x_BITS values aren't all the same, * we have to scale to get consistent RGB-space distances. * This code won't work right if HIST_G_BITS is less than the other two, * but that shouldn't ever be true. */ c0 = (c0max - c0min) << (HIST_G_BITS-HIST_R_BITS); c1 = (c1max - c1min); c2 = (c2max - c2min) << (HIST_G_BITS-HIST_B_BITS); boxp->volume = c0*c0 + c1*c1 + c2*c2; /* Now scan remaining volume of box and compute population */ ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++, histp++) if (*histp != 0) { ccount++; } } boxp->colorcount = ccount; } LOCAL int median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes, int desired_colors) /* Repeatedly select and split the largest box until we have enough boxes */ { int n,lb; int c0,c1,c2,cmax; register boxptr b1,b2; while (numboxes < desired_colors) { /* Select box to split. * Current algorithm: by population for first half, then by volume. */ if (numboxes*2 <= desired_colors) { b1 = find_biggest_color_pop(boxlist, numboxes); } else { b1 = find_biggest_volume(boxlist, numboxes); } if (b1 == NULL) /* no splittable boxes left! */ break; b2 = &boxlist[numboxes]; /* where new box will go */ /* Copy the color bounds to the new box. */ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; /* Choose which axis to split the box on. * Current algorithm: longest scaled axis. * See notes in update_box about scaling distances... */ c0 = (b1->c0max - b1->c0min) << (HIST_G_BITS-HIST_R_BITS); c1 = (b1->c1max - b1->c1min); c2 = (b1->c2max - b1->c2min) << (HIST_G_BITS-HIST_B_BITS); cmax = c0; n = 0; if (c1 > cmax) { cmax = c1; n = 1; } if (c2 > cmax) { n = 2; } /* Choose split point along selected axis, and update box bounds. * Current algorithm: split at halfway point. * (Since the box has been shrunk to minimum volume, * any split will produce two nonempty subboxes.) * Note that lb value is max for lower box, so must be < old max. */ switch (n) { case 0: lb = (b1->c0max + b1->c0min) / 2; b1->c0max = lb; b2->c0min = lb+1; break; case 1: lb = (b1->c1max + b1->c1min) / 2; b1->c1max = lb; b2->c1min = lb+1; break; case 2: lb = (b1->c2max + b1->c2min) / 2; b1->c2max = lb; b2->c2min = lb+1; break; } /* Update stats for boxes */ update_box(cinfo, b1); update_box(cinfo, b2); numboxes++; } return numboxes; } LOCAL void compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor) /* Compute representative color for a box, put it in colormap[icolor] */ { /* Current algorithm: mean weighted by pixels (not colors) */ /* Note it is important to get the rounding correct! */ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; histptr histp; int c0,c1,c2; int c0min,c0max,c1min,c1max,c2min,c2max; long count; long total = 0; long c0total = 0; long c1total = 0; long c2total = 0; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { histp = & histogram[c0][c1][c2min]; for (c2 = c2min; c2 <= c2max; c2++) { if ((count = *histp++) != 0) { total += count; c0total += ((c0 << R_SHIFT) + ((1<>1)) * count; c1total += ((c1 << G_SHIFT) + ((1<>1)) * count; c2total += ((c2 << B_SHIFT) + ((1<>1)) * count; } } } cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); } LOCAL void select_colors (j_decompress_ptr cinfo) /* Master routine for color selection */ { boxptr boxlist; int numboxes; int desired = cinfo->desired_number_of_colors; int i; /* Allocate workspace for box list */ boxlist = (boxptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, desired * SIZEOF(box)); /* Initialize one box containing whole space */ numboxes = 1; boxlist[0].c0min = 0; boxlist[0].c0max = MAXJSAMPLE >> R_SHIFT; boxlist[0].c1min = 0; boxlist[0].c1max = MAXJSAMPLE >> G_SHIFT; boxlist[0].c2min = 0; boxlist[0].c2max = MAXJSAMPLE >> B_SHIFT; /* Shrink it to actually-used volume and set its statistics */ update_box(cinfo, & boxlist[0]); /* Perform median-cut to produce final box list */ numboxes = median_cut(cinfo, boxlist, numboxes, desired); /* Compute the representative color for each box, fill colormap */ for (i = 0; i < numboxes; i++) compute_color(cinfo, & boxlist[i], i); cinfo->actual_number_of_colors = numboxes; TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes); } /* * These routines are concerned with the time-critical task of mapping input * colors to the nearest color in the selected colormap. * * We re-use the histogram space as an "inverse color map", essentially a * cache for the results of nearest-color searches. All colors within a * histogram cell will be mapped to the same colormap entry, namely the one * closest to the cell's center. This may not be quite the closest entry to * the actual input color, but it's almost as good. A zero in the cache * indicates we haven't found the nearest color for that cell yet; the array * is cleared to zeroes before starting the mapping pass. When we find the * nearest color for a cell, its colormap index plus one is recorded in the * cache for future use. The pass2 scanning routines call fill_inverse_cmap * when they need to use an unfilled entry in the cache. * * Our method of efficiently finding nearest colors is based on the "locally * sorted search" idea described by Heckbert and on the incremental distance * calculation described by Spencer W. Thomas in chapter III.1 of Graphics * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that * the distances from a given colormap entry to each cell of the histogram can * be computed quickly using an incremental method: the differences between * distances to adjacent cells themselves differ by a constant. This allows a * fairly fast implementation of the "brute force" approach of computing the * distance from every colormap entry to every histogram cell. Unfortunately, * it needs a work array to hold the best-distance-so-far for each histogram * cell (because the inner loop has to be over cells, not colormap entries). * The work array elements have to be INT32s, so the work array would need * 256Kb at our recommended precision. This is not feasible in DOS machines. * * To get around these problems, we apply Thomas' method to compute the * nearest colors for only the cells within a small subbox of the histogram. * The work array need be only as big as the subbox, so the memory usage * problem is solved. Furthermore, we need not fill subboxes that are never * referenced in pass2; many images use only part of the color gamut, so a * fair amount of work is saved. An additional advantage of this * approach is that we can apply Heckbert's locality criterion to quickly * eliminate colormap entries that are far away from the subbox; typically * three-fourths of the colormap entries are rejected by Heckbert's criterion, * and we need not compute their distances to individual cells in the subbox. * The speed of this approach is heavily influenced by the subbox size: too * small means too much overhead, too big loses because Heckbert's criterion * can't eliminate as many colormap entries. Empirically the best subbox * size seems to be about 1/512th of the histogram (1/8th in each direction). * * Thomas' article also describes a refined method which is asymptotically * faster than the brute-force method, but it is also far more complex and * cannot efficiently be applied to small subboxes. It is therefore not * useful for programs intended to be portable to DOS machines. On machines * with plenty of memory, filling the whole histogram in one shot with Thomas' * refined method might be faster than the present code --- but then again, * it might not be any faster, and it's certainly more complicated. */ /* log2(histogram cells in update box) for each axis; this can be adjusted */ #define BOX_R_LOG (HIST_R_BITS-3) #define BOX_G_LOG (HIST_G_BITS-3) #define BOX_B_LOG (HIST_B_BITS-3) #define BOX_R_ELEMS (1<actual_number_of_colors; int maxc0, maxc1, maxc2; int centerc0, centerc1, centerc2; int i, x, ncolors; INT32 minmaxdist, min_dist, max_dist, tdist; INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */ /* Compute true coordinates of update box's upper corner and center. * Actually we compute the coordinates of the center of the upper-corner * histogram cell, which are the upper bounds of the volume we care about. * Note that since ">>" rounds down, the "center" values may be closer to * min than to max; hence comparisons to them must be "<=", not "<". */ maxc0 = minc0 + ((1 << BOX_R_SHIFT) - (1 << R_SHIFT)); centerc0 = (minc0 + maxc0) >> 1; maxc1 = minc1 + ((1 << BOX_G_SHIFT) - (1 << G_SHIFT)); centerc1 = (minc1 + maxc1) >> 1; maxc2 = minc2 + ((1 << BOX_B_SHIFT) - (1 << B_SHIFT)); centerc2 = (minc2 + maxc2) >> 1; /* For each color in colormap, find: * 1. its minimum squared-distance to any point in the update box * (zero if color is within update box); * 2. its maximum squared-distance to any point in the update box. * Both of these can be found by considering only the corners of the box. * We save the minimum distance for each color in mindist[]; * only the smallest maximum distance is of interest. */ minmaxdist = 0x7FFFFFFFL; for (i = 0; i < numcolors; i++) { /* We compute the squared-c0-distance term, then add in the other two. */ x = GETJSAMPLE(cinfo->colormap[0][i]); if (x < minc0) { tdist = x - minc0; min_dist = tdist*tdist; tdist = x - maxc0; max_dist = tdist*tdist; } else if (x > maxc0) { tdist = x - maxc0; min_dist = tdist*tdist; tdist = x - minc0; max_dist = tdist*tdist; } else { /* within cell range so no contribution to min_dist */ min_dist = 0; if (x <= centerc0) { tdist = x - maxc0; max_dist = tdist*tdist; } else { tdist = x - minc0; max_dist = tdist*tdist; } } x = GETJSAMPLE(cinfo->colormap[1][i]); if (x < minc1) { tdist = x - minc1; min_dist += tdist*tdist; tdist = x - maxc1; max_dist += tdist*tdist; } else if (x > maxc1) { tdist = x - maxc1; min_dist += tdist*tdist; tdist = x - minc1; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc1) { tdist = x - maxc1; max_dist += tdist*tdist; } else { tdist = x - minc1; max_dist += tdist*tdist; } } x = GETJSAMPLE(cinfo->colormap[2][i]); if (x < minc2) { tdist = x - minc2; min_dist += tdist*tdist; tdist = x - maxc2; max_dist += tdist*tdist; } else if (x > maxc2) { tdist = x - maxc2; min_dist += tdist*tdist; tdist = x - minc2; max_dist += tdist*tdist; } else { /* within cell range so no contribution to min_dist */ if (x <= centerc2) { tdist = x - maxc2; max_dist += tdist*tdist; } else { tdist = x - minc2; max_dist += tdist*tdist; } } mindist[i] = min_dist; /* save away the results */ if (max_dist < minmaxdist) minmaxdist = max_dist; } /* Now we know that no cell in the update box is more than minmaxdist * away from some colormap entry. Therefore, only colors that are * within minmaxdist of some part of the box need be considered. */ ncolors = 0; for (i = 0; i < numcolors; i++) { if (mindist[i] <= minmaxdist) colorlist[ncolors++] = (JSAMPLE) i; } return ncolors; } LOCAL void find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2, int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[]) /* Find the closest colormap entry for each cell in the update box, * given the list of candidate colors prepared by find_nearby_colors. * Return the indexes of the closest entries in the bestcolor[] array. * This routine uses Thomas' incremental distance calculation method to * find the distance from a colormap entry to successive cells in the box. */ { int ic0, ic1, ic2; int i, icolor; register INT32 * bptr; /* pointer into bestdist[] array */ JSAMPLE * cptr; /* pointer into bestcolor[] array */ INT32 dist0, dist1; /* initial distance values */ register INT32 dist2; /* current distance in inner loop */ INT32 xx0, xx1; /* distance increments */ register INT32 xx2; INT32 inc0, inc1, inc2; /* initial values for increments */ /* This array holds the distance to the nearest-so-far color for each cell */ INT32 bestdist[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS]; /* Initialize best-distance for each cell of the update box */ bptr = bestdist; for (i = BOX_R_ELEMS*BOX_G_ELEMS*BOX_B_ELEMS-1; i >= 0; i--) *bptr++ = 0x7FFFFFFFL; /* For each color selected by find_nearby_colors, * compute its distance to the center of each cell in the box. * If that's less than best-so-far, update best distance and color number. */ /* Nominal steps between cell centers ("x" in Thomas article) */ #define STEP_R (1 << R_SHIFT) #define STEP_G (1 << G_SHIFT) #define STEP_B (1 << B_SHIFT) for (i = 0; i < numcolors; i++) { icolor = GETJSAMPLE(colorlist[i]); /* Compute (square of) distance from minc0/c1/c2 to this color */ inc0 = minc0 - (int) GETJSAMPLE(cinfo->colormap[0][icolor]); dist0 = inc0*inc0; inc1 = minc1 - (int) GETJSAMPLE(cinfo->colormap[1][icolor]); dist0 += inc1*inc1; inc2 = minc2 - (int) GETJSAMPLE(cinfo->colormap[2][icolor]); dist0 += inc2*inc2; /* Form the initial difference increments */ inc0 = inc0 * (2 * STEP_R) + STEP_R * STEP_R; inc1 = inc1 * (2 * STEP_G) + STEP_G * STEP_G; inc2 = inc2 * (2 * STEP_B) + STEP_B * STEP_B; /* Now loop over all cells in box, updating distance per Thomas method */ bptr = bestdist; cptr = bestcolor; xx0 = inc0; for (ic0 = BOX_R_ELEMS-1; ic0 >= 0; ic0--) { dist1 = dist0; xx1 = inc1; for (ic1 = BOX_G_ELEMS-1; ic1 >= 0; ic1--) { dist2 = dist1; xx2 = inc2; for (ic2 = BOX_B_ELEMS-1; ic2 >= 0; ic2--) { if (dist2 < *bptr) { *bptr = dist2; *cptr = (JSAMPLE) icolor; } dist2 += xx2; xx2 += 2 * STEP_B * STEP_B; bptr++; cptr++; } dist1 += xx1; xx1 += 2 * STEP_G * STEP_G; } dist0 += xx0; xx0 += 2 * STEP_R * STEP_R; } } } LOCAL void fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2) /* Fill the inverse-colormap entries in the update box that contains */ /* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */ /* we can fill as many others as we wish.) */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; int minc0, minc1, minc2; /* lower left corner of update box */ int ic0, ic1, ic2; register JSAMPLE * cptr; /* pointer into bestcolor[] array */ register histptr cachep; /* pointer into main cache array */ /* This array lists the candidate colormap indexes. */ JSAMPLE colorlist[MAXNUMCOLORS]; int numcolors; /* number of candidate colors */ /* This array holds the actually closest colormap index for each cell. */ JSAMPLE bestcolor[BOX_R_ELEMS * BOX_G_ELEMS * BOX_B_ELEMS]; /* Convert cell coordinates to update box ID */ c0 >>= BOX_R_LOG; c1 >>= BOX_G_LOG; c2 >>= BOX_B_LOG; /* Compute true coordinates of update box's origin corner. * Actually we compute the coordinates of the center of the corner * histogram cell, which are the lower bounds of the volume we care about. */ minc0 = (c0 << BOX_R_SHIFT) + ((1 << R_SHIFT) >> 1); minc1 = (c1 << BOX_G_SHIFT) + ((1 << G_SHIFT) >> 1); minc2 = (c2 << BOX_B_SHIFT) + ((1 << B_SHIFT) >> 1); /* Determine which colormap entries are close enough to be candidates * for the nearest entry to some cell in the update box. */ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist); /* Determine the actually nearest colors. */ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist, bestcolor); /* Save the best color numbers (plus 1) in the main cache array */ c0 <<= BOX_R_LOG; /* convert ID back to base cell indexes */ c1 <<= BOX_G_LOG; c2 <<= BOX_B_LOG; cptr = bestcolor; for (ic0 = 0; ic0 < BOX_R_ELEMS; ic0++) { for (ic1 = 0; ic1 < BOX_G_ELEMS; ic1++) { cachep = & histogram[c0+ic0][c1+ic1][c2]; for (ic2 = 0; ic2 < BOX_B_ELEMS; ic2++) { *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1); } } } } /* * Map some rows of pixels to the output colormapped representation. */ METHODDEF void pass2_nodither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs no dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; register JSAMPROW inptr, outptr; register histptr cachep; register int c0, c1, c2; int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; for (row = 0; row < num_rows; row++) { inptr = input_buf[row]; outptr = output_buf[row]; for (col = width; col > 0; col--) { /* get pixel value and index into the cache */ c0 = GETJSAMPLE(*inptr++) >> R_SHIFT; c1 = GETJSAMPLE(*inptr++) >> G_SHIFT; c2 = GETJSAMPLE(*inptr++) >> B_SHIFT; cachep = & histogram[c0][c1][c2]; /* If we have not seen this color before, find nearest colormap entry */ /* and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, c0,c1,c2); /* Now emit the colormap index for this cell */ *outptr++ = (JSAMPLE) (*cachep - 1); } } } METHODDEF void pass2_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows) /* This version performs Floyd-Steinberg dithering */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ register FSERRPTR errorptr; /* => fserrors[] at column before current */ JSAMPROW inptr; /* => current input pixel */ JSAMPROW outptr; /* => current output pixel */ histptr cachep; int dir; /* +1 or -1 depending on direction */ int dir3; /* 3*dir, for advancing errorptr */ int row; JDIMENSION col; JDIMENSION width = cinfo->output_width; JSAMPLE *range_limit = cinfo->sample_range_limit; int *error_limit = cquantize->error_limiter; JSAMPROW colormap0 = cinfo->colormap[0]; JSAMPROW colormap1 = cinfo->colormap[1]; JSAMPROW colormap2 = cinfo->colormap[2]; SHIFT_TEMPS for (row = 0; row < num_rows; row++) { inptr = input_buf[row]; outptr = output_buf[row]; if (cquantize->on_odd_row) { /* work right to left in this row */ inptr += (width-1) * 3; /* so point to rightmost pixel */ outptr += width-1; dir = -1; dir3 = -3; errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */ cquantize->on_odd_row = FALSE; /* flip for next time */ } else { /* work left to right in this row */ dir = 1; dir3 = 3; errorptr = cquantize->fserrors; /* => entry before first real column */ cquantize->on_odd_row = TRUE; /* flip for next time */ } /* Preset error values: no error propagated to first pixel from left */ cur0 = cur1 = cur2 = 0; /* and no error propagated to row below yet */ belowerr0 = belowerr1 = belowerr2 = 0; bpreverr0 = bpreverr1 = bpreverr2 = 0; for (col = width; col > 0; col--) { /* curN holds the error propagated from the previous pixel on the * current line. Add the error propagated from the previous line * to form the complete error correction term for this pixel, and * round the error term (which is expressed * 16) to an integer. * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct * for either sign of the error value. * Note: errorptr points to *previous* column's array entry. */ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4); cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4); cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4); /* Limit the error using transfer function set by init_error_limit. * See comments with init_error_limit for rationale. */ cur0 = error_limit[cur0]; cur1 = error_limit[cur1]; cur2 = error_limit[cur2]; /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE. * The maximum error is +- MAXJSAMPLE (or less with error limiting); * this sets the required size of the range_limit array. */ cur0 += GETJSAMPLE(inptr[0]); cur1 += GETJSAMPLE(inptr[1]); cur2 += GETJSAMPLE(inptr[2]); cur0 = GETJSAMPLE(range_limit[cur0]); cur1 = GETJSAMPLE(range_limit[cur1]); cur2 = GETJSAMPLE(range_limit[cur2]); /* Index into the cache with adjusted pixel value */ cachep = & histogram[cur0 >> R_SHIFT][cur1 >> G_SHIFT][cur2 >> B_SHIFT]; /* If we have not seen this color before, find nearest colormap */ /* entry and update the cache */ if (*cachep == 0) fill_inverse_cmap(cinfo, cur0>>R_SHIFT, cur1>>G_SHIFT, cur2>>B_SHIFT); /* Now emit the colormap index for this cell */ { register int pixcode = *cachep - 1; *outptr = (JSAMPLE) pixcode; /* Compute representation error for this pixel */ cur0 -= GETJSAMPLE(colormap0[pixcode]); cur1 -= GETJSAMPLE(colormap1[pixcode]); cur2 -= GETJSAMPLE(colormap2[pixcode]); } /* Compute error fractions to be propagated to adjacent pixels. * Add these into the running sums, and simultaneously shift the * next-line error sums left by 1 column. */ { register LOCFSERROR bnexterr, delta; bnexterr = cur0; /* Process component 0 */ delta = cur0 * 2; cur0 += delta; /* form error * 3 */ errorptr[0] = (FSERROR) (bpreverr0 + cur0); cur0 += delta; /* form error * 5 */ bpreverr0 = belowerr0 + cur0; belowerr0 = bnexterr; cur0 += delta; /* form error * 7 */ bnexterr = cur1; /* Process component 1 */ delta = cur1 * 2; cur1 += delta; /* form error * 3 */ errorptr[1] = (FSERROR) (bpreverr1 + cur1); cur1 += delta; /* form error * 5 */ bpreverr1 = belowerr1 + cur1; belowerr1 = bnexterr; cur1 += delta; /* form error * 7 */ bnexterr = cur2; /* Process component 2 */ delta = cur2 * 2; cur2 += delta; /* form error * 3 */ errorptr[2] = (FSERROR) (bpreverr2 + cur2); cur2 += delta; /* form error * 5 */ bpreverr2 = belowerr2 + cur2; belowerr2 = bnexterr; cur2 += delta; /* form error * 7 */ } /* At this point curN contains the 7/16 error value to be propagated * to the next pixel on the current line, and all the errors for the * next line have been shifted over. We are therefore ready to move on. */ inptr += dir3; /* Advance pixel pointers to next column */ outptr += dir; errorptr += dir3; /* advance errorptr to current column */ } /* Post-loop cleanup: we must unload the final error values into the * final fserrors[] entry. Note we need not unload belowerrN because * it is for the dummy column before or after the actual array. */ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ errorptr[1] = (FSERROR) bpreverr1; errorptr[2] = (FSERROR) bpreverr2; } } /* * Initialize the error-limiting transfer function (lookup table). * The raw F-S error computation can potentially compute error values of up to * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be * much less, otherwise obviously wrong pixels will be created. (Typical * effects include weird fringes at color-area boundaries, isolated bright * pixels in a dark area, etc.) The standard advice for avoiding this problem * is to ensure that the "corners" of the color cube are allocated as output * colors; then repeated errors in the same direction cannot cause cascading * error buildup. However, that only prevents the error from getting * completely out of hand; Aaron Giles reports that error limiting improves * the results even with corner colors allocated. * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty * well, but the smoother transfer function used below is even better. Thanks * to Aaron Giles for this idea. */ LOCAL void init_error_limit (j_decompress_ptr cinfo) /* Allocate and fill in the error_limiter table */ { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; int * table; int in, out; table = (int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int)); table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */ cquantize->error_limiter = table; #ifdef GILES #define STEPSIZE ((MAXJSAMPLE+1)/32) /* Map errors 1:1 up to +- MAXJSAMPLE/32 */ out = 0; for (in = 0; in < STEPSIZE; in++, out++) { table[in] = out; table[-in] = -out; } /* Map errors 1:2 up to +- 3*MAXJSAMPLE/32 */ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { table[in] = out; table[-in] = -out; } /* Map errors 1:4 up to +- 7*MAXJSAMPLE/32 */ for (; in < STEPSIZE*7; in++, out += (in&3) ? 0 : 1) { table[in] = out; table[-in] = -out; } /* Map errors 1:8 up to +- 15*MAXJSAMPLE/32 */ for (; in < STEPSIZE*15; in++, out += (in&7) ? 0 : 1) { table[in] = out; table[-in] = -out; } /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ for (; in <= MAXJSAMPLE; in++) { table[in] = out; table[-in] = -out; } #else #define STEPSIZE ((MAXJSAMPLE+1)/16) /* Map errors 1:1 up to +- MAXJSAMPLE/16 */ out = 0; for (in = 0; in < STEPSIZE; in++, out++) { table[in] = out; table[-in] = -out; } /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) { table[in] = out; table[-in] = -out; } /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */ for (; in <= MAXJSAMPLE; in++) { table[in] = out; table[-in] = -out; } #endif #undef STEPSIZE } /* * Finish up at the end of each pass. */ METHODDEF void finish_pass1 (j_decompress_ptr cinfo) { /* Select the representative colors and fill in cinfo->colormap */ select_colors(cinfo); } METHODDEF void finish_pass2 (j_decompress_ptr cinfo) { /* no work */ } /* * Initialize for each processing pass. */ METHODDEF void start_pass (j_decompress_ptr cinfo, boolean is_pre_scan) { my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize; hist3d histogram = cquantize->histogram; int i; if (is_pre_scan) { /* Set up method pointers */ cquantize->pub.color_quantize = prescan_quantize; cquantize->pub.finish_pass = finish_pass1; } else { /* Set up method pointers */ if (cinfo->use_dithering) cquantize->pub.color_quantize = pass2_dither; else cquantize->pub.color_quantize = pass2_nodither; cquantize->pub.finish_pass = finish_pass2; } /* Zero the histogram or inverse color map */ for (i = 0; i < HIST_R_ELEMS; i++) { jzero_far((void FAR *) histogram[i], HIST_G_ELEMS*HIST_B_ELEMS * SIZEOF(histcell)); } } /* * Module initialization routine for 2-pass color quantization. */ GLOBAL void jinit_2pass_quantizer (j_decompress_ptr cinfo) { my_cquantize_ptr cquantize; int i; cquantize = (my_cquantize_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(my_cquantizer)); cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize; cquantize->pub.start_pass = start_pass; /* Make sure jdmaster didn't give me a case I can't handle */ if (cinfo->out_color_components != 3) ERREXIT(cinfo, JERR_PIPE_BUG); /* Make sure color count is acceptable */ i = (cinfo->colormap != NULL) ? cinfo->actual_number_of_colors : cinfo->desired_number_of_colors; /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */ if (i < 8) ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8); /* Make sure colormap indexes can be represented by JSAMPLEs */ if (i > MAXNUMCOLORS) ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS); /* Allocate the histogram/inverse colormap storage */ cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_R_ELEMS * SIZEOF(hist2d)); for (i = 0; i < HIST_R_ELEMS; i++) { cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_G_ELEMS*HIST_B_ELEMS * SIZEOF(histcell)); } /* Allocate storage for the completed colormap, * unless it has been supplied by the application. * We do this now since it is FAR storage and may affect * the memory manager's space calculations. */ if (cinfo->colormap == NULL) { cinfo->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) cinfo->desired_number_of_colors, (JDIMENSION) 3); } /* Allocate Floyd-Steinberg workspace if necessary. */ /* This isn't needed until pass 2, but again it is FAR storage. */ if (cinfo->use_dithering) { size_t arraysize = (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))); cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize); /* Initialize the propagated errors to zero. */ jzero_far((void FAR *) cquantize->fserrors, arraysize); cquantize->on_odd_row = FALSE; init_error_limit(cinfo); } } #endif /* QUANT_2PASS_SUPPORTED */ \ No newline at end of file diff --git a/Independent JPEG Group/jutils.c b/Independent JPEG Group/jutils.c new file mode 100644 index 0000000..42b6a2d --- /dev/null +++ b/Independent JPEG Group/jutils.c @@ -0,0 +1 @@ +/* * jutils.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains miscellaneous utility routines needed for both * compression and decompression. * Note we prefix all global names with "j" to minimize conflicts with * a surrounding application. */ #define JPEG_INTERNALS #include "jinclude.h" #include "jpeglib.h" /* * Arithmetic utilities */ GLOBAL long jdiv_round_up (long a, long b) /* Compute a/b rounded up to next integer, ie, ceil(a/b) */ /* Assumes a >= 0, b > 0 */ { return (a + b - 1L) / b; } GLOBAL long jround_up (long a, long b) /* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */ /* Assumes a >= 0, b > 0 */ { a += b - 1L; return a - (a % b); } /* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays * and coefficient-block arrays. This won't work on 80x86 because the arrays * are FAR and we're assuming a small-pointer memory model. However, some * DOS compilers provide far-pointer versions of memcpy() and memset() even * in the small-model libraries. These will be used if USE_FMEM is defined. * Otherwise, the routines below do it the hard way. (The performance cost * is not all that great, because these routines aren't very heavily used.) */ #ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */ #define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size) #define FMEMZERO(target,size) MEMZERO(target,size) #else /* 80x86 case, define if we can */ #ifdef USE_FMEM #define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size)) #define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size)) #endif #endif GLOBAL void jcopy_sample_rows (JSAMPARRAY input_array, int source_row, JSAMPARRAY output_array, int dest_row, int num_rows, JDIMENSION num_cols) /* Copy some rows of samples from one place to another. * num_rows rows are copied from input_array[source_row++] * to output_array[dest_row++]; these areas should not overlap. * The source and destination arrays must be at least as wide as num_cols. */ { register JSAMPROW inptr, outptr; #ifdef FMEMCOPY register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE)); #else register JDIMENSION count; #endif register int row; input_array += source_row; output_array += dest_row; for (row = num_rows; row > 0; row--) { inptr = *input_array++; outptr = *output_array++; #ifdef FMEMCOPY FMEMCOPY(outptr, inptr, count); #else for (count = num_cols; count > 0; count--) *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */ #endif } } GLOBAL void jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row, JDIMENSION num_blocks) /* Copy a row of coefficient blocks from one place to another. */ { #ifdef FMEMCOPY FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF))); #else register JCOEFPTR inptr, outptr; register long count; inptr = (JCOEFPTR) input_row; outptr = (JCOEFPTR) output_row; for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) { *outptr++ = *inptr++; } #endif } GLOBAL void jzero_far (void FAR * target, size_t bytestozero) /* Zero out a chunk of FAR memory. */ /* This might be sample-array data, block-array data, or alloc_medium data. */ { #ifdef FMEMZERO FMEMZERO(target, bytestozero); #else register char FAR * ptr = (char FAR *) target; register size_t count; for (count = bytestozero; count > 0; count--) { *ptr++ = 0; } #endif } \ No newline at end of file diff --git a/Independent JPEG Group/jversion.h b/Independent JPEG Group/jversion.h new file mode 100644 index 0000000..1591ae5 --- /dev/null +++ b/Independent JPEG Group/jversion.h @@ -0,0 +1 @@ +/* * jversion.h * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains software version identification. */ #define JVERSION "5alpha2 4-May-94" #define JCOPYRIGHT "Copyright (C) 1994, Thomas G. Lane" \ No newline at end of file diff --git a/Independent JPEG Group/libjpeg.doc b/Independent JPEG Group/libjpeg.doc new file mode 100644 index 0000000..1ff5a11 --- /dev/null +++ b/Independent JPEG Group/libjpeg.doc @@ -0,0 +1 @@ +USING THE IJG JPEG LIBRARY Copyright (C) 1994, Thomas G. Lane. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. This file describes how to use the IJG JPEG library within an application program. Read it if you want to write a program that uses the library. The file example.c provides heavily commented skeleton code for calling the JPEG library. Also see jpeglib.h (the include file to be used by application programs) for full details about data structures and function parameter lists. The library source code, of course, is the ultimate reference. Note that there have been *major* changes from the application interface presented by IJG version 4 and earlier versions. The old design had several inherent limitations, and it had accumulated a lot of cruft as we added features while trying to minimize application-interface changes. We have sacrificed backward compatibility in the version 5 rewrite, but we think the improvements justify this. TABLE OF CONTENTS ----------------- Overview: Functions provided by the library Outline of typical usage Basic library usage: Data formats Compression details Decompression details Mechanics of usage: include files, linking, etc Advanced features: Compression parameter selection Decompression parameter selection Special color spaces Error handling Compressed data handling (source and destination managers) I/O suspension Abbreviated datastreams and multiple images Special markers Downsampled image data Progress monitoring Memory management Library compile-time options Portability considerations Notes for MS-DOS implementors You should read at least the overview and basic usage sections before trying to program with the library. The sections on advanced features can be read if and when you need them. OVERVIEW ======== Functions provided by the library --------------------------------- The IJG JPEG library provides C code to read and write JPEG-compressed image files. The surrounding application program receives or supplies image data a scanline at a time, using a straightforward uncompressed image format. All details of color conversion and other preprocessing/postprocessing can be handled by the library. The library includes a substantial amount of code that is not covered by the JPEG standard but is necessary for typical applications of JPEG. These functions preprocess the image before JPEG compression or postprocess it after decompression. They include colorspace conversion, downsampling/upsampling, and color quantization. The application indirectly selects use of this code by specifying the format in which it wishes to supply or receive image data. For example, if colormapped output is requested, then the decompression library automatically invokes color quantization. A wide range of quality vs. speed tradeoffs are possible in JPEG processing, and even more so in decompression postprocessing. The decompression library provides multiple implementations that cover most of the useful tradeoffs, ranging from very-high-quality down to fast-preview operation. On the compression side we have generally not provided low-quality choices, since compression is normally less time-critical. It should be understood that the low-quality modes may not meet the JPEG standard's accuracy requirements; nonetheless, they are useful for viewers. A word about functions *not* provided by the library. We handle a subset of the ISO JPEG standard; most baseline and extended-sequential JPEG processes are supported. (Our subset includes all features now in common use.) Unsupported ISO options include: * Progressive storage (may be supported in future versions) * Hierarchical storage * Lossless JPEG * Arithmetic entropy coding (unsupported for legal reasons) * DNL marker * Nonintegral subsampling ratios We support both 8- and 12-bit data precision, but this is a compile-time choice rather than a run-time choice; hence it is difficult to use both precisions in a single application. By itself, the library handles only interchange JPEG datastreams --- in particular the widely used JFIF file format. The library can be used by surrounding code to process interchange or abbreviated JPEG datastreams that are embedded in more complex file formats. (For example, we anticipate that Sam Leffler's LIBTIFF library will use this code to support the revised TIFF JPEG format.) Outline of typical usage ------------------------ The rough outline of a JPEG compression operation is: Allocate and initialize a JPEG compression object Specify the destination for the compressed data (eg, a file) Set parameters for compression, including image size & colorspace jpeg_start_compress(...); while (scan lines remain to be written) jpeg_write_scanlines(...); jpeg_finish_compress(...); Release the JPEG compression object A JPEG compression object holds parameters and working state for the JPEG library. We make creation/destruction of the object separate from starting or finishing compression of an image; the same object can be re-used for a series of image compression operations. This makes it easy to re-use the same parameter settings for a sequence of images. Re-use of a JPEG object also has important implications for processing abbreviated JPEG datastreams, as discussed later. The image data to be compressed is supplied to jpeg_write_scanlines() from in-memory buffers. If the application is doing file-to-file compression, reading image data from the source file is the application's responsibility. The library emits compressed data by calling a "data destination manager", which typically will write the data into a file; but the application can provide its own destination manager to do something else. Similarly, the rough outline of a JPEG decompression operation is: Allocate and initialize a JPEG decompression object Specify the source of the compressed data (eg, a file) Call jpeg_read_header() to obtain image info Set parameters for decompression jpeg_start_decompress(...); while (scan lines remain to be read) jpeg_read_scanlines(...); jpeg_finish_decompress(...); Release the JPEG decompression object This is comparable to the compression outline except that reading the datastream header is a separate step. By doing this, information about the image's size, colorspace, etc is available when the application selects decompression parameters. For example, the application can choose an output scaling ratio that will fit the image into the available screen size. The decompression library obtains compressed data by calling a data source manager, which typically will read the data from a file; but other behaviors can be obtained with a custom source manager. Decompressed data is delivered into in-memory buffers passed to jpeg_read_scanlines(). It is possible to abort an incomplete compression or decompression operation by calling jpeg_abort(); or, if you do not need to retain the JPEG object, simply release it by calling jpeg_destroy(). JPEG compression and decompression objects are two separate struct types. However, they share some common fields, and certain routines such as jpeg_destroy() can work on either type of object. The JPEG library has no static variables: all state is in the compression or decompression object. Therefore it is possible to process multiple compression and decompression operations concurrently, using multiple JPEG objects. Both compression and decompression can be done in an incremental memory-to- memory fashion, if suitable source/destination managers are used. However, there are some restrictions on the processing that can be done in this mode. See the section on "I/O suspension" for more details. BASIC LIBRARY USAGE =================== Data formats ------------ Before diving into procedural details, it is helpful to understand the image data format that the JPEG library expects or returns. The standard input image format is a rectangular array of pixels, with each pixel having the same number of "component" values (color channels). You must specify how many components there are and the colorspace interpretation of the components. Most applications will use RGB data (three components per pixel) or grayscale data (one component per pixel). Note that there is no provision for colormapped input. You can feed in a colormapped image by expanding it to full-color format. However JPEG often doesn't work very well with colormapped source data, because of dithering noise. This is discussed in more detail in the JPEG FAQ and the other references mentioned in the README file. Pixels are stored by scanlines, with each scanline running from left to right. If you are working with color data, then the component values for each pixel are adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an array of data type JSAMPLE --- which is generally "unsigned char", unless you've changed jmorecfg.h. A 2-D array of pixels is formed by making a list of pointers to the starts of scanlines; the scanlines need not be adjacent in memory. Even if you process just one scanline at a time, you must make a one-element pointer array to serve this purpose. Pointers to JSAMPLE rows are of type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY. The library accepts or supplies one or more complete scanlines per call; it is not possible to process part of a row at a time. Scanlines are always processed top-to-bottom. You can process an entire image in one call if you have it all in memory, but usually it's more convenient to process one scanline at a time. For best results, source data values should have the precision specified by BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress data that's only 6 bits/channel, you should left-justify each value in a byte before passing it to the compressor. If you need to compress data that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12. (See "Library compile-time options", later.) The data format returned by the decompressor is the same in all details, except that colormapped data is supported. If you request colormapped output then the returned data array contains a single JSAMPLE per pixel; its value is an index into a color map. The color map is represented as a 2-D JSAMPARRAY in which each row holds the values of one color component, that is, colormap[i][j] is the value of the i'th color component for pixel value (map index) j. Note that since the colormap indexes are stored in JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE (ie, at most 256 colors for an 8-bit JPEG library). Compression details ------------------- Here we revisit the JPEG compression outline given in the overview. 1. Allocate and initialize a JPEG compression object. A JPEG compression object is a "struct jpeg_compress_struct" (plus a bunch of subsidiary structures which are allocated via malloc(), but the application doesn't control those directly). This struct can be just a local variable in the calling routine, if a single routine is going to execute the whole JPEG compression sequence. Otherwise it can be static or allocated from malloc(). You will also need a structure representing a JPEG error handler. The part of this that the library cares about is a "struct jpeg_error_mgr". If you are providing your own error handler, you'll typically want to embed the jpeg_error_mgr struct in a larger structure; this is discussed later under "Error handling". For now we'll assume you are just using the default error handler. The default error handler will print JPEG error/warning messages on stderr, and it will call exit() if a fatal error occurs. You must initialize the error handler structure, store a pointer to it into the JPEG object's "err" field, and then call jpeg_create_compress() to initialize the rest of the JPEG object. Typical code for this step, if you are using the default error handler, is struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; ... cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_create_compress allocates a small amount of memory, so it could fail if you are out of memory. In that case it will exit via the error handler. 2. Specify the destination for the compressed data (eg, a file). As previously mentioned, the JPEG library delivers compressed data to a "data destination" module. The library includes one data destination module which knows how to write to a stdio stream. You can use your own destination module if you want to do something else, as discussed later. If you use the standard destination module, you must open the target stdio stream beforehand. Typical code for this step looks like: FILE * outfile; ... if ((outfile = fopen(filename, "wb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); exit(1); } jpeg_stdio_dest(&cinfo, outfile); where the last line invokes the standard destination module. WARNING: it is critical that the binary compressed data be delivered to the output file unchanged. On non-Unix systems the stdio library may perform newline translation or otherwise corrupt binary data. To suppress this behavior, you may need to use a "b" option to fopen (as shown above), or use setmode() or another routine to put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that has been found to work on many systems. You can select the data destination after setting other parameters (step 3), if that's more convenient. You may not change the destination between calling jpeg_start_compress() and jpeg_finish_compress(). 3. Set parameters for compression, including image size & colorspace. You must supply information about the source image by setting the following fields in the JPEG object (cinfo structure): image_width Width of image, in pixels image_height Height of image, in pixels input_components Number of color channels (samples per pixel) in_color_space Color space of source image The image dimensions are, hopefully, obvious. JPEG supports image dimensions of 1 to 64K pixels in either direction. The input color space is typically RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special color spaces", later, for more info.) The in_color_space field should be assigned one of the enum constants JCS_RGB or JCS_GRAYSCALE. JPEG has a large number of compression parameters that determine how the image is encoded. Most applications don't need or want to know about all these parameters. You can set all the parameters to reasonable defaults by calling jpeg_set_defaults(); then, if there are particular values you want to change, you can do so after that. The "Compression parameter selection" section tells about all the parameters. You must set in_color_space correctly before calling jpeg_set_defaults(), because the defaults depend on the source image colorspace. However the other three source image parameters need not be valid until you call jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more than once, if that happens to be convenient. Typical code for a 24-bit RGB source image is cinfo.image_width = Width; /* image width and height, in pixels */ cinfo.image_height = Height; cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ jpeg_set_defaults(&cinfo); /* Make optional parameter settings here */ 4. jpeg_start_compress(...); After you have established the data destination and set all the necessary source image info and other parameters, call jpeg_start_compress() to begin a compression cycle. This will initialize internal state, allocate working storage, and emit the first few bytes of the JPEG datastream header. Typical code: jpeg_start_compress(&cinfo, TRUE); The "TRUE" parameter ensures that a complete JPEG interchange datastream will be written. This is appropriate in most cases. If you think you might want to use an abbreviated datastream, read the section on abbreviated datastreams, later. Once you have called jpeg_start_compress(), you may not alter any JPEG parameters or other fields of the JPEG object until you have completed the compression cycle. 5. while (scan lines remain to be written) jpeg_write_scanlines(...); Now write all the required image data by calling jpeg_write_scanlines() one or more times. You can pass one or more scanlines in each call, up to the total image height. In most applications it is convenient to pass just one or a few scanlines at a time. The expected format for the passed data is discussed under "Data formats", above. Image data should be written in top-to-bottom scanline order. The JPEG spec contains some weasel wording about how top and bottom are application-defined terms (a curious interpretation of the English language...) but if you want your files to be compatible with everyone else's, you WILL use top-to-bottom order. If the source data must be read in bottom-to-top order, you can use the JPEG library's virtual array mechanism to invert the data efficiently. Examples of this can be found in the sample application cjpeg. The library maintains a count of the number of scanlines written so far in the next_scanline field of the JPEG object. Usually you can just use this variable as the loop counter, so that the loop test looks like "while (cinfo.next_scanline < cinfo.image_height)". Code for this step depends heavily on the way that you store the source data. example.c shows the following code for the case of a full-size 2-D source array containing 3-byte RGB pixels: JSAMPROW row_pointer[1]; /* pointer to a single row */ int row_stride; /* physical row width in buffer */ row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */ while (cinfo.next_scanline < cinfo.image_height) { row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_write_scanlines() returns the number of scanlines actually written. This will normally be equal to the number passed in, so you can usually ignore the return value. It is different in just two cases: * If you try to write more scanlines than the declared image height, the additional scanlines are ignored. * If you use a suspending data destination manager, output buffer overrun will cause the compressor to return before accepting all the passed lines. This feature is discussed under "I/O suspension", below. The normal stdio destination manager will NOT cause this to happen. In any case, the return value is the same as the change in the value of next_scanline. 6. jpeg_finish_compress(...); After all the image data has been written, call jpeg_finish_compress() to complete the compression cycle. This step is ESSENTIAL to ensure that the last bufferload of data is written to the data destination. jpeg_finish_compress() also releases working memory associated with the JPEG object. Typical code: jpeg_finish_compress(&cinfo); If using the stdio destination manager, don't forget to close the output stdio stream if necessary. If you have requested a multi-pass operating mode, such as Huffman code optimization, jpeg_finish_compress() will perform the additional passes using data buffered by the first pass. In this case jpeg_finish_compress() may take quite a while to complete. With the default compression parameters, this will not happen. It is an error to call jpeg_finish_compress() before writing the necessary total number of scanlines. If you wish to abort compression, call jpeg_abort() as discussed below. After completing a compression cycle, you may dispose of the JPEG object as discussed next, or you may use it to compress another image. In that case return to step 2, 3, or 4 as appropriate. If you do not change the destination manager, the new datastream will be written to the same target. If you do not change any JPEG parameters, the new datastream will be written with the same parameters as before. Note that you can change the input image dimensions freely between cycles, but if you change the input colorspace, you should call jpeg_set_defaults() to adjust for the new colorspace; and then you'll need to repeat all of step 3. 7. Release the JPEG compression object. When you are done with a JPEG compression object, destroy it by calling jpeg_destroy_compress(). This will free all subsidiary memory. Or you can call jpeg_destroy() which works for either compression or decompression objects --- this may be more convenient if you are sharing code between compression and decompression cases. (Actually, these routines are equivalent except for the declared type of the passed pointer. To avoid gripes from ANSI C compilers, pass a j_common_ptr to jpeg_destroy().) If you allocated the jpeg_compress_struct structure from malloc(), freeing it is your responsibility --- jpeg_destroy() won't. Ditto for the error handler structure. Typical code: jpeg_destroy_compress(&cinfo); 8. Aborting. If you decide to abort a compression cycle before finishing, you can clean up in either of two ways: * If you don't need the JPEG object any more, just call jpeg_destroy_compress() or jpeg_destroy() to release memory. This is legitimate at any point after calling jpeg_create_compress() --- in fact, it's safe even if jpeg_create_compress() fails. * If you want to re-use the JPEG object, call jpeg_abort_compress(), or jpeg_abort() which works on both compression and decompression objects. This will return the object to an idle state, releasing any working memory. jpeg_abort() is allowed at any time after successful object creation. Note that cleaning up the data destination, if required, is your responsibility. Decompression details --------------------- Here we revisit the JPEG decompression outline given in the overview. 1. Allocate and initialize a JPEG decompression object. This is just like initialization for compression, as discussed above, except that the object is a "struct jpeg_decompress_struct" and you call jpeg_create_decompress(). Error handling is exactly the same. Typical code: struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; ... cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); (Both here and in the IJG code, we usually use variable name "cinfo" for both compression and decompression objects.) 2. Specify the source of the compressed data (eg, a file). As previously mentioned, the JPEG library reads compressed data from a "data source" module. The library includes one data source module which knows how to read from a stdio stream. You can use your own source module if you want to do something else, as discussed later. If you use the standard source module, you must open the source stdio stream beforehand. Typical code for this step looks like: FILE * infile; ... if ((infile = fopen(filename, "rb")) == NULL) { fprintf(stderr, "can't open %s\n", filename); exit(1); } jpeg_stdio_src(&cinfo, infile); where the last line invokes the standard source module. WARNING: it is critical that the binary compressed data be read unchanged. On non-Unix systems the stdio library may perform newline translation or otherwise corrupt binary data. To suppress this behavior, you may need to use a "b" option to fopen (as shown above), or use setmode() or another routine to put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that has been found to work on many systems. You may not change the data source between calling jpeg_read_header() and jpeg_finish_decompress(). If you wish to read a series of JPEG images from a single source file, you should repeat the jpeg_read_header() to jpeg_finish_decompress() sequence without reinitializing either the JPEG object or the data source module; this prevents buffered input data from being discarded. 3. Call jpeg_read_header() to obtain image info. Typical code for this step is just jpeg_read_header(&cinfo, TRUE); This will read the source datastream header markers, up to the beginning of the compressed data proper. On return, the image dimensions and other info have been stored in the JPEG object. The application may wish to consult this information before selecting decompression parameters. More complex code is necessary if * A suspending data source is used --- in that case jpeg_read_header() may return before it has read all the header data. See "I/O suspension", below. The normal stdio source manager will NOT cause this to happen. * Abbreviated JPEG files are to be processed. See the section on abbreviated datastreams. Standard applications that deal only in interchange JPEG files need not be concerned with this case either. It is permissible to stop at this point if you just wanted to find out the image dimensions and other header info for a JPEG file. In that case, call jpeg_destroy() when you are done with the JPEG object, or call jpeg_abort() to return it to an idle state before selecting a new data source and reading another header. 4. Set parameters for decompression. jpeg_read_header() sets appropriate default decompression parameters based on the properties of the image (in particular, its colorspace). However, you may well want to alter these defaults before beginning the decompression. For example, the default is to produce full color output from a color file. If you want colormapped output you must ask for it. Other options allow the returned image to be scaled and allow various speed/quality tradeoffs to be selected. "Decompression parameter selection", below, gives details. If the defaults are appropriate, nothing need be done at this step. Note that all default values are set by each call to jpeg_read_header(). If you reuse a decompression object, you cannot expect your parameter settings to be preserved across cycles, as you can for compression. You must adjust parameter values each time. 5. jpeg_start_decompress(...); Once the parameter values are satisfactory, call jpeg_start_decompress() to begin decompression. This will initialize internal state, allocate working memory, and prepare for returning data. Typical code is just jpeg_start_decompress(&cinfo); If you have requested a multi-pass operating mode, such as 2-pass color quantization, jpeg_start_decompress() will do everything needed before data output can begin. In this case jpeg_start_decompress() may take quite a while to complete. With a single-scan (fully interleaved) JPEG file and default decompression parameters, this will not happen; jpeg_start_decompress() will return quickly. After this call, the final output image dimensions, including any requested scaling, are available in the JPEG object; so is the selected colormap, if colormapped output has been requested. Useful fields include output_width image width and height, as scaled output_height out_color_components # of color components in out_color_space output_components # of color components returned per pixel colormap the selected colormap, if any actual_number_of_colors number of entries in colormap output_components is 1 (a colormap index) when quantizing colors; otherwise it equals out_color_components. It is the number of JSAMPLE values that will be emitted per pixel in the output arrays. Typically you will need to allocate data buffers to hold the incoming image. You will need output_width * output_components JSAMPLEs per scanline in your output buffer, and a total of output_height scanlines will be returned. Note: if you are using the JPEG library's internal memory manager to allocate data buffers (as djpeg does), then the manager's protocol requires that you request large buffers *before* calling jpeg_start_decompress(). This is a little tricky since the output_XXX fields are not normally valid then. You can make them valid by calling jpeg_calc_output_dimensions() after setting the relevant parameters (scaling, output color space, and quantization flag). 6. while (scan lines remain to be read) jpeg_read_scanlines(...); Now you can read the decompressed image data by calling jpeg_read_scanlines() one or more times. At each call, you pass in the maximum number of scanlines to be read (ie, the height of your working buffer); jpeg_read_scanlines() will return up to that many lines. The return value is the number of lines actually read. The format of the returned data is discussed under "Data formats", above. Image data is returned in top-to-bottom scanline order. If you must write out the image in bottom-to-top order, you can use the JPEG library's virtual array mechanism to invert the data efficiently. Examples of this can be found in the sample application djpeg. The library maintains a count of the number of scanlines returned so far in the output_scanline field of the JPEG object. Usually you can just use this variable as the loop counter, so that the loop test looks like "while (cinfo.output_scanline < cinfo.output_height)". (Note that the test should NOT be against image_height, unless you never use scaling. The image_height field is the height of the original unscaled image.) If you don't use a suspending data source, it is safe to assume that jpeg_read_scanlines() reads at least one scanline per call, until the bottom of the image has been reached. If you use a buffer larger than one scanline, it is NOT safe to assume that jpeg_read_scanlines() fills it. In any case, the return value is the same as the change in the value of output_scanline. 7. jpeg_finish_decompress(...); After all the image data has been read, call jpeg_finish_decompress() to complete the decompression cycle. This causes working memory associated with the JPEG object to be released. Typical code: jpeg_finish_decompress(&cinfo); If using the stdio source manager, don't forget to close the source stdio stream if necessary. It is an error to call jpeg_finish_decompress() before reading the correct total number of scanlines. If you wish to abort compression, call jpeg_abort() as discussed below. After completing a decompression cycle, you may dispose of the JPEG object as discussed next, or you may use it to decompress another image. In that case return to step 2 or 3 as appropriate. If you do not change the source manager, the next image will be read from the same source. 8. Release the JPEG decompression object. When you are done with a JPEG decompression object, destroy it by calling jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of destroying compression objects applies here too. Typical code: jpeg_destroy_decompress(&cinfo); 9. Aborting. You can abort a decompression cycle by calling jpeg_destroy_decompress() or jpeg_destroy() if you don't need the JPEG object any more, or jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object. The previous discussion of aborting compression cycles applies here too. Mechanics of usage: include files, linking, etc ----------------------------------------------- Applications using the JPEG library should include the header file jpeglib.h to obtain declarations of data types and routines. Before including jpeglib.h, include system headers that define at least the typedefs FILE and size_t. On ANSI-conforming systems, including is sufficient; on older Unix systems, you may need to define size_t. If the application needs to refer to individual JPEG library error codes, also include jerror.h to define those symbols. jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are installing the JPEG header files in a system directory, you will want to install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h. (It may be worth pointing out that the core JPEG library does not actually require the stdio library: only the default source/destination managers and error handler need it. You can use the library in a stdio-less environment if you replace those modules. More info about the minimum system library requirements may be found in jinclude.h.) The most convenient way to include the JPEG code into your executable program is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix machines) and reference it at your link step. If you use only half of the library (only compression or only decompression), only that much code will be included from the library, unless your linker is hopelessly brain-damaged. Most of the supplied makefiles build libjpeg.a automatically (see install.doc). On some systems your application may need to set up a signal handler to ensure that temporary files are deleted if the program is interrupted. This is most critical if you are on MS-DOS and use the jmemdos.c memory manager back end; it will try to grab extended memory for temp files, and that space will NOT be freed automatically. See cjpeg.c or djpeg.c for an example signal handler. ADVANCED FEATURES ================= Compression parameter selection ------------------------------- This section describes all the optional parameters you can set for JPEG compression, as well as the "helper" routines provided to assist in this task. Proper setting of some parameters requires detailed understanding of the JPEG standard; if you don't know what a parameter is for, it's best not to mess with it! See REFERENCES in the README file for pointers to more info about JPEG. It's a good idea to call jpeg_set_defaults() first, even if you plan to set all the parameters; that way your code is more likely to work with future JPEG libraries that have additional parameters. For the same reason, we recommend you use a helper routine where one is provided, in preference to twiddling cinfo fields directly. The helper routines are: jpeg_set_defaults (j_compress_ptr cinfo) This routine sets all JPEG parameters to reasonable defaults, using only the input image's color space (field in_color_space, which must already be set in cinfo). Many applications will only need to use this routine and perhaps jpeg_set_quality(). jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) Sets the JPEG file's colorspace (field jpeg_color_space) as specified, and sets other color-space-dependent parameters appropriately. See "Special color spaces", below, before using this. A large number of parameters, including all per-component parameters, are set by this routine; if you want to twiddle individual parameters you should call jpeg_set_colorspace() before rather than after. jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) Constructs JPEG quantization tables appropriate for the indicated quality setting. The quality value is expressed on the 0..100 scale recommended by IJG (cjpeg's "-quality" switch uses this routine). Note that the exact mapping from quality values to tables may change in future IJG releases as more is learned about DCT quantization. If the force_baseline parameter is TRUE, then the quantization table entries are constrained to the range 1..255 for full JPEG baseline compatibility. In the current implementation, this only makes a difference for quality settings below 25, and it effectively prevents very small/low quality files from being generated. The IJG decoder is capable of reading the non-baseline files generated at low quality settings when force_baseline is FALSE, but other decoders may not be. jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, boolean force_baseline) Same as jpeg_set_quality() except that the generated tables are the sample tables given in the JPEC spec section K.1, multiplied by the specified scale factor (which is expressed as a percentage; thus scale_factor = 100 reproduces the spec's tables). Note that larger scale factors give lower quality. This entry point is useful for conforming to the Adobe PostScript DCT conventions, but we do not recommend linear scaling as a user-visible quality scale otherwise. force_baseline again constrains the computed table entries to 1..255. int jpeg_quality_scaling (int quality) Converts a value on the IJG-recommended quality scale to a linear scaling percentage. Note that this routine may change or go away in future releases --- IJG may choose to adopt a nonlinear scaling, in which case the premise of this routine collapses. jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, const unsigned int *basic_table, int scale_factor, boolean force_baseline)); Allows an arbitrary quantization table to be created. which_tbl indicates which table slot to fill. basic_table points to an array of 64 unsigned ints given in JPEG zigzag order. These values are multiplied by scale_factor/100 and then clamped to the range 1..65535 (or to 1..255 if force_baseline is TRUE). Compression parameters (cinfo fields) include: boolean optimize_coding TRUE causes the compressor to compute optimal Huffman coding tables for the image. This requires an extra pass over the data and therefore costs a good deal of space and time. The default is FALSE, which tells the compressor to use the supplied or default Huffman tables. In most cases optimal tables save only a few percent of file size compared to the default tables. Note that when this is TRUE, you need not supply Huffman tables at all, and any you do supply will be overwritten. int smoothing_factor If non-zero, the input image is smoothed; the value should be 1 for minimal smoothing to 100 for maximum smoothing. Consult jcsample.c for details of the smoothing algorithm. [Ignored in version 5alpha2, but should be implemented before v5 release.] unsigned int restart_interval int restart_in_rows To emit restart markers in the JPEG file, set one of these nonzero. Set restart_interval to specify the exact interval in MCU blocks. Set restart_in_rows to specify the interval in MCU rows. (If restart_in_rows is not 0, then restart_interval is set after the image width in MCUs is computed.) J_COLOR_SPACE jpeg_color_space int num_components The JPEG color space and corresponding number of components; see "Special color spaces", below, for more info. We recommend using jpeg_set_color_space() if you want to change these. boolean write_JFIF_header If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space (ie, YCbCr or grayscale) is selected, otherwise FALSE. UINT8 density_unit UINT16 X_density UINT16 Y_density The resolution information to be written into the JFIF marker; not used otherwise. density_unit may be 0 for unknown, 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1 indicating square pixels of unknown size. boolean write_Adobe_marker If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK, or YCCK is selected, otherwise FALSE. It is generally a bad idea to set both write_JFIF_header and write_Adobe_marker. In fact, you probably shouldn't change the default settings at all --- the default behavior ensures that the JPEG file's color space can be recognized by the decoder. JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS] Pointers to coefficient quantization tables, one per table slot, or NULL if no table is defined for a slot. Usually these should be set via one of the above helper routines; jpeg_add_quant_table() is general enough to define any quantization table. The other routines will set up table slot 0 for luminance quality and table slot 1 for chrominance. If you insist on creating tables directly, use jpeg_alloc_quant_table(); the struct JQUANT_TBL is *not* large enough, because there are additional hidden fields. JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS] JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS] Pointers to Huffman coding tables, one per table slot, or NULL if no table is defined for a slot. Slots 0 and 1 are filled with the JPEG sample tables by jpeg_set_defaults(). If you want to experiment with your own Huffman tables, allocate a table with jpeg_alloc_huff_table() unless the table slot pointer is already non-NULL. (The struct JHUFF_TBL is *not* large enough.) Then fill the bits[] and huffval[] arrays in the structure. Note that optimal Huffman tables can be computed for an image by setting optimize_coding, as discussed above; there's seldom any need to mess with providing your own Huffman tables. There are some additional cinfo fields which are not documented here because you currently can't change them; for example, you can't set arith_code TRUE because arithmetic coding is unsupported. Per-component parameters are stored in the struct cinfo.comp_info[i] for component number i. Note that components here refer to components of the JPEG color space, *not* the source image color space. A suitably large comp_info[] array is allocated by jpeg_set_defaults(); if you choose not to use that routine, it's up to you to allocate the array. int component_id The one-byte identifier code to be recorded in the JPEG file for this component. For the standard color spaces, we recommend you leave the default values alone. int h_samp_factor int v_samp_factor Horizontal and vertical sampling factors for the component; must be 1..4 according to the JPEG standard. Note that larger sampling factors indicate a higher-resolution component; many people find this behavior quite unintuitive. The default values are 2,2 for luminance components and 1,1 for chrominance components, except for grayscale where 1,1 is used. int quant_tbl_no Quantization table number for component. The default value is 0 for luminance components and 1 for chrominance components. int dc_tbl_no int ac_tbl_no DC and AC entropy coding table numbers. The default values are 0 for luminance components and 1 for chrominance components. int component_index Must equal the component's index in comp_info[]. Don't mess with this. Decompression parameter selection --------------------------------- Decompression parameter selection is somewhat simpler than compression parameter selection, since all of the JPEG internal parameters are recorded in the source file and need not be supplied by the application. (Unless you are working with abbreviated files, in which case see "Abbreviated datastreams", below.) Decompression parameters control the postprocessing done on the image to deliver it in a format suitable for the application's use. Many of the parameters control speed/quality tradeoffs, in which faster decompression may be obtained at the price of a poorer-quality image. The defaults select the highest quality (slowest) processing. The following fields in the JPEG object are set by jpeg_read_header() and may be useful to the application in choosing decompression parameters: JDIMENSION image_width Width and height of image JDIMENSION image_height int num_components Number of color components J_COLOR_SPACE jpeg_color_space Colorspace of image boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen UINT8 density_unit Resolution data from JFIF marker UINT16 X_density UINT16 Y_density boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen UINT8 Adobe_transform Color transform code from Adobe marker The JPEG color space, unfortunately, is something of a guess since the JPEG standard proper does not provide a way to record it. In practice most files adhere to the JFIF or Adobe conventions, and the decoder will recognize these correctly. See "Special color spaces", below, for more info. The decompression parameters that the application may set are: J_COLOR_SPACE out_color_space Output color space. jpeg_read_header() sets an appropriate default based on jpeg_color_space; typically it will be RGB or grayscale. The application can force this to grayscale to get grayscale output from a color file. Grayscale output is faster than full color since the color components need not be processed. (Note that not all possible color space transforms are currently implemented; you may need to extend jdcolor.c if you want an unusual conversion.) unsigned int scale_num, scale_denom Scale the image by the fraction scale_num/scale_denom. Default is 1/1, or no scaling. Currently, the only supported scaling ratios are 1/1, 1/2, 1/4, and 1/8. (The library design allows for arbitrary scaling ratios but this is not likely to be implemented any time soon.) Smaller scaling ratios permit significantly faster decoding since fewer pixels need be processed and a simpler IDCT method can be used. boolean do_block_smoothing If TRUE, apply cross-block smoothing. Default is FALSE. Smoothing sometimes improves the appearance of very-low-quality-setting files. (Not currently implemented in v5, and may not be any time soon.) boolean do_fancy_upsampling If TRUE, do careful upsampling of chroma components. If FALSE, a faster but sloppier method is used. Default is TRUE. The visual impact of the sloppier method is often very small. boolean quantize_colors If set TRUE, colormapped output will be delivered. Default is FALSE, meaning that full-color output will be delivered. The next three parameters are relevant only if quantize_colors is TRUE. int desired_number_of_colors Maximum number of colors to use in generating a library-supplied color map (the actual number of colors is returned in a different field). Default 256. Ignored when the application supplies its own color map. boolean two_pass_quantize If TRUE, an extra pass over the image is made to select a custom color map for the image. This usually looks a lot better than the one-size- fits-all colormap that is used otherwise. Default is TRUE. Ignored when the application supplies its own color map. boolean use_dithering If TRUE, Floyd-Steinberg dithering is applied. F-S dithering is fairly slow but usually improves the perceived quality significantly. Default is TRUE. When quantize_colors is TRUE, the target color map is described by the next two fields. colormap is set to NULL by jpeg_read_header(). The application can supply a color map by setting colormap non-NULL and setting actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress() selects a color map and sets these fields. JSAMPARRAY colormap The color map represented as a 2-D pixel array of out_color_components rows and actual_number_of_colors columns. Ignored if not quantizing. int actual_number_of_colors The number of colors in the color map. The output image dimensions are given by the following fields. These are computed from the source image dimensions and the decompression parameters by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions() to obtain the values that will result from the current parameter settings. This can be useful if you are trying to pick a scaling ratio that will get close to a desired target size. It's also important if you are using the JPEG library's memory manager to allocate output buffer space, because you are supposed to request such buffers *before* jpeg_start_decompress(). JDIMENSION output_width Actual dimensions of output image. JDIMENSION output_height int out_color_components Number of color components in out_color_space. int output_components Number of color components returned. int rec_outbuf_height Recommended height of scanline buffer. When quantizing colors, output_components is 1, indicating a single color map index per pixel. Otherwise it equals out_color_components. The output arrays are required to be output_width * output_components JSAMPLEs wide. rec_outbuf_height is the recommended minimum height (in scanlines) of the buffer passed to jpeg_read_scanlines(). If the buffer is smaller, the library will still work, but space and time will be wasted due to unnecessary data copying. As of version 5alpha1, rec_outbuf_height is always 1, but future high-speed processing modes may set it to larger values (2 to 4 would be typical). If you are going to ask for a high-speed processing mode, you may as well go to the extra work of avoiding data copying... Special color spaces -------------------- The JPEG standard itself is "color blind" and doesn't specify any particular color space. It is customary to convert color data to a luminance/chrominance color space before compressing, since this permits greater compression. The existing de-facto JPEG file format standards specify YCbCr or grayscale data (JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special applications such as multispectral images, other color spaces can be used, but it must be understood that such files will be unportable. The JPEG library can handle the most common colorspace conversions (namely RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown color space, passing it through without conversion. If you deal extensively with an unusual color space, you can easily extend the library to understand additional color spaces and perform appropriate conversions. For compression, the source data's color space is specified by field in_color_space. This is transformed to the JPEG file's color space given by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color space depending on in_color_space, but you can override this by calling jpeg_set_colorspace(). Of course you must select a supported transformation. jccolor.c currently supports the following transformations: RGB => YCbCr RGB => GRAYSCALE YCbCr => GRAYSCALE CMYK => YCCK plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB, YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN. The de-facto file format standards (JFIF and Adobe) specify APPn markers that indicate the color space of the JPEG file. It is important to ensure that these are written correctly, or omitted if the JPEG file's color space is not one of the ones supported by the de-facto standards. jpeg_set_colorspace() will set the compression parameters to include or omit the APPn markers properly, so long as it is told the truth about the JPEG color space. For example, if you are writing some random 3-component color space without conversion, don't try to fake out the library by setting in_color_space and jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an APPn marker of your own devising to identify the colorspace --- see "Special markers", below. When told that the color space is UNKNOWN, the library will default to using luminance-quality compression parameters for all color components. You may well want to change these parameters. See the source code for jpeg_set_colorspace(), in jcparam.c, for details. For decompression, the JPEG file's color space is given in jpeg_color_space, and this is transformed to the output color space out_color_space. jpeg_read_header's setting of jpeg_color_space can be relied on if the file conforms to JFIF or Adobe conventions, but otherwise it is no better than a guess. If you know the JPEG file's color space for certain, you can override jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also selects a default output color space based on (its guess of) jpeg_color_space; set out_color_space to override this. Again you must select a supported transformation. jdcolor.c currently supports YCbCr => GRAYSCALE YCbCr => RGB YCCK => CMYK as well as the null transforms. Error handling -------------- When the default error handler is used, any error detected inside the JPEG routines will cause a message to be printed on stderr, followed by exit(). You can supply your own error handling routines to override this behavior and to control the treatment of nonfatal warnings and trace/debug messages. The file example.c illustrates the most common case, which is to have the application regain control after an error rather than exiting. The JPEG library never writes any message directly; it always goes through the error handling routines. Three classes of messages are recognized: * Fatal errors: the library cannot continue. * Warnings: the library can continue, but the data is corrupt, and a damaged output image is likely to result. * Trace/informational messages. These come with a trace level indicating the importance of the message; you can control the verbosity of the program by adjusting the maximum trace level that will be displayed. You may, if you wish, simply replace the entire JPEG error handling module (jerror.c) with your own code. However, you can avoid code duplication by only replacing some of the routines depending on the behavior you need. This is accomplished by calling jpeg_std_error() as usual, but then overriding some of the method pointers in the jpeg_error_mgr struct, as illustrated by example.c. All of the error handling routines will receive a pointer to the JPEG object (a j_common_ptr which points to either a jpeg_compress_struct or a jpeg_decompress_struct; if you need to tell which, test the is_decompressor field). This struct includes a pointer to the error manager struct in its "err" field. Frequently, custom error handler routines will need to access additional data which is not known to the JPEG library or the standard error handler. The most convenient way to do this is to embed either the JPEG object or the jpeg_error_mgr struct in a larger structure that contains additional fields; then casting the passed pointer provides access to the additional fields. Again, see example.c for one way to do it. The individual methods that you might wish to override are: error_exit (j_common_ptr cinfo) Receives control for a fatal error. Information sufficient to generate the error message has been stored in cinfo->err; call output_message to display it. Control must NOT return to the caller; generally this routine will exit() or longjmp() somewhere. Typically you would override this routine to get rid of the exit() default behavior. Note that if you continue processing, you should clean up the JPEG object with jpeg_abort() or jpeg_destroy(). output_message (j_common_ptr cinfo) Actual output of any JPEG message. Override this to send messages somewhere other than stderr. Note that this method does not know how to generate a message, only where to send it. format_message (j_common_ptr cinfo, char * buffer) Constructs a readable error message string based on the error info stored in cinfo->err. This method is called by output_message. Few applications should need to override this method. One possible reason for doing so is to implement dynamic switching of error message language. emit_message (j_common_ptr cinfo, int msg_level) Decide whether or not to emit a warning or trace message; if so, calls output_message. The main reason for overriding this method would be to abort on warnings. msg_level is -1 for warnings, 0 and up for trace messages. Only error_exit() and emit_message() are called from the rest of the JPEG library; the other two are internal to the error handler. The actual message texts are stored in an array of strings which is pointed to by the field err->jpeg_message_table. The messages are numbered from 0 to err->last_jpeg_message, and it is these code numbers that are used in the JPEG library code. You could replace the message texts (for instance, with messages in French or German) by changing the message table pointer. See jerror.h for the default texts. CAUTION: this table will almost certainly change or grow from one library version to the next. It may be useful for an application to add its own message texts that are handled by the same mechanism. The error handler supports a second "add-on" message table for this purpose. To define an addon table, set the pointer err->addon_message_table and the message numbers err->first_addon_message and err->last_addon_message. If you number the addon messages beginning at 1000 or so, you won't have to worry about conflicts with the library's built-in messages. See the sample applications cjpeg/djpeg for an example of using addon messages (the addon messages are defined in cderror.h). Actual invocation of the error handler is done via macros defined in jerror.h: ERREXITn(...) for fatal errors WARNMSn(...) for corrupt-data warnings TRACEMSn(...) for trace and informational messages. These macros store the message code and any additional parameters into the error handler struct, then invoke the error_exit() or emit_message() method. The variants of each macro are for varying numbers of additional parameters. The additional parameters are inserted into the generated message using standard printf() format codes. See jerror.h and jerror.c for further details. Compressed data handling (source and destination managers) ---------------------------------------------------------- The JPEG compression library sends its compressed data to a "destination manager" module. The default destination manager just writes the data to a stdio stream, but you can provide your own manager to do something else. Similarly, the decompression library calls a "source manager" to obtain the compressed data; you can provide your own source manager if you want the data to come from somewhere other than a stdio stream. In both cases, compressed data is processed a bufferload at a time: the destination or source manager provides a work buffer, and the library invokes the manager only when the buffer is filled or emptied. (You could define a one-character buffer to force the manager to be invoked for each byte, but that would be rather inefficient.) The buffer's size and location are controlled by the manager, not by the library. For example, if you desired to decompress a JPEG datastream that was all in memory, you could just make the buffer pointer and length point to the original data in memory. Then the buffer-reload procedure would be invoked only if the decompressor ran off the end of the datastream, which would indicate an erroneous datastream. The work buffer is defined as an array of datatype JOCTET, which is generally "char" or "unsigned char". On a machine where char is not exactly 8 bits wide, you must define JOCTET as a wider data type and then modify the data source and destination modules to transcribe the work arrays into 8-bit units on external storage. A data destination manager struct contains a pointer and count defining the next byte to write in the work buffer and the remaining free space: JOCTET * next_output_byte; /* => next byte to write in buffer */ size_t free_in_buffer; /* # of byte spaces remaining in buffer */ The library increments the pointer and decrements the count until the buffer is filled. The manager's empty_output_buffer method must reset the pointer and count. The manager is expected to remember the buffer's starting address and total size in private fields not visible to the library. A data destination manager provides three methods: init_destination (j_compress_ptr cinfo) Initialize destination. This is called by jpeg_start_compress() before any data is actually written. It must initialize next_output_byte and free_in_buffer. free_in_buffer must be initialized to a positive value. empty_output_buffer (j_compress_ptr cinfo) This is called whenever the buffer has filled (free_in_buffer reaches zero). In typical applications, it should write out the *entire* buffer (use the saved start address and buffer length; ignore the current state of next_output_byte and free_in_buffer). Then reset the pointer & count to the start of the buffer, and return TRUE indicating that the buffer has been dumped. free_in_buffer must be set to a positive value when TRUE is returned. A FALSE return should only be used when I/O suspension is desired (this operating mode is discussed in the next section). term_destination (j_compress_ptr cinfo) Terminate destination --- called by jpeg_finish_compress() after all data has been written. In most applications, this must flush any data remaining in the buffer. Use either next_output_byte or free_in_buffer to determine how much data is in the buffer. term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you want the destination manager to be cleaned up during an abort, you must do it yourself. You will also need code to create a jpeg_destination_mgr struct, fill in its method pointers, and insert a pointer to the struct into the "dest" field of the JPEG compression object. This can be done in-line in your setup code if you like, but it's probably cleaner to provide a separate routine similar to the jpeg_stdio_dest() routine of the supplied destination manager. Decompression source managers follow a parallel design, but with some additional frammishes. The source manager struct contains a pointer and count defining the next byte to read from the work buffer and the number of bytes remaining: const JOCTET * next_input_byte; /* => next byte to read from buffer */ size_t bytes_in_buffer; /* # of bytes remaining in buffer */ The library increments the pointer and decrements the count until the buffer is emptied. The manager's fill_input_buffer method must reset the pointer and count. In most applications, the manager must remember the buffer's starting address and total size in private fields not visible to the library. A data source manager provides five methods: init_source (j_decompress_ptr cinfo) Initialize source. This is called by jpeg_read_header() before any data is actually read. Unlike init_destination(), it may leave bytes_in_buffer set to 0 (in which case a fill_input_buffer() call will occur immediately). fill_input_buffer (j_decompress_ptr cinfo) This is called whenever bytes_in_buffer has reached zero and more data is wanted. In typical applications, it should read fresh data into the buffer (ignoring the current state of next_input_byte and bytes_in_buffer), reset the pointer & count to the start of the buffer, and return TRUE indicating that the buffer has been reloaded. It is not necessary to fill the buffer entirely, only to obtain at least one more byte. bytes_in_buffer MUST be set to a positive value if TRUE is returned. A FALSE return should only be used when I/O suspension is desired (this mode is discussed in the next section). skip_input_data (j_decompress_ptr cinfo, long num_bytes) Skip num_bytes worth of data. The buffer pointer and count should be advanced over num_bytes input bytes, refilling the buffer as needed. This is used to skip over a potentially large amount of uninteresting data (such as an APPn marker). In some applications it may be possible to optimize away the reading of the skipped data, but it's not clear that being smart is worth much trouble; large skips are uncommon. bytes_in_buffer may be zero on return. A zero or negative skip count should be treated as a no-op. resync_to_restart (j_decompress_ptr cinfo) This routine is called only when the decompressor has failed to find a restart (RSTn) marker where one is expected. Its mission is to find a suitable point for resuming decompression. For most applications, we recommend that you just use the default resync procedure, jpeg_resync_to_restart(). However, if you are able to back up in the input data stream, or if you have a-priori knowledge about the likely location of restart markers, you may be able to do better. Read the read_restart_marker() and jpeg_resync_to_restart() routines in jdmarker.c if you think you'd like to implement your own resync procedure. term_source (j_decompress_ptr cinfo) Terminate source --- called by jpeg_finish_decompress() after all data has been read. Often a no-op. For both fill_input_buffer() and skip_input_data(), there is no such thing as an EOF return. If the end of the file has been reached, the routine has a choice of exiting via ERREXIT() or inserting fake data into the buffer. In most cases, generating a warning message and inserting a fake EOI marker is the best course of action --- this will allow the decompressor to output however much of the image is there. In pathological cases, the decompressor may swallow the EOI and again demand data ... just keep feeding it fake EOIs. jdatasrc.c illustrates the recommended error recovery behavior. term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want the source manager to be cleaned up during an abort, you must do it yourself. You will also need code to create a jpeg_source_mgr struct, fill in its method pointers, and insert a pointer to the struct into the "src" field of the JPEG decompression object. This can be done in-line in your setup code if you like, but it's probably cleaner to provide a separate routine similar to the jpeg_stdio_src() routine of the supplied source manager. For more information, consult the stdio source and destination managers in jdatasrc.c and jdatadst.c. I/O suspension -------------- Some applications need to use the JPEG library as an incremental memory-to- memory filter: when the compressed data buffer is filled or emptied, they want control to return to the outer loop, rather than expecting that the buffer can be flushed or reloaded within the data source/destination manager subroutine. The library supports this need by providing an "I/O suspension" mode, which we describe in this section. The I/O suspension mode is a limited solution: it works only in the simplest operating modes (namely single-pass processing of single-scan JPEG files), and it has several other restrictions which are documented below. Furthermore, nothing is guaranteed about the maximum amount of time spent in any one call to the library, so a single-threaded application may still have response-time problems. If you need multi-pass processing or guaranteed response time, we suggest you "bite the bullet" and implement a real multi-tasking capability. To use I/O suspension, cooperation is needed between the calling application and the data source or destination manager; you will always need a custom source/destination manager. (Please read the above section if you haven't already.) The basic idea is that the empty_output_buffer() or fill_input_buffer() routine is a no-op, merely returning FALSE to indicate that it has done nothing. Upon seeing this, the JPEG library suspends operation and returns to its caller. The surrounding application is responsible for emptying or refilling the work buffer before calling the JPEG library again. Compression suspension: For compression suspension, use an empty_output_buffer() routine that returns FALSE; typically it will not do anything else. This will cause the compressor to return to the caller of jpeg_write_scanlines(), with the return value indicating that not all the supplied scanlines have been accepted. The application must make more room in the output buffer, adjust the pointer/count appropriately, and then call jpeg_write_scanlines() again, pointing to the first unconsumed scanline. When forced to suspend, the compressor will backtrack to a convenient stopping point (usually the start of the current MCU); it will regenerate some output data when restarted. Therefore, although empty_output_buffer() is only called when the buffer is filled, you should NOT dump out the entire buffer, only the data up to the current position of next_output_byte/free_in_buffer. The data beyond that point will be regenerated after resumption. Because of the backtracking behavior, a good-size output buffer is essential for efficiency; you don't want the compressor to suspend often. (In fact, an overly small buffer could lead to infinite looping, if a single MCU required more data than would fit in the buffer.) We recommend a buffer of at least several Kbytes. You may want to insert explicit code to ensure that you don't call jpeg_write_scanlines() unless there is a reasonable amount of space in the output buffer; in other words, flush the buffer before trying to compress more data. The JPEG compressor does not support suspension while it is trying to write JPEG markers at the beginning and end of the file. This means that * At the beginning of a compression operation, there must be enough free space in the output buffer to hold the header markers (typically 600 or so bytes). The recommended buffer size is bigger than this anyway, so this is not a problem as long as you start with an empty buffer. However, this restriction might catch you if you insert large special markers, such as a JFIF thumbnail image. * When you call jpeg_finish_compress(), there must be enough space in the output buffer to emit any buffered data and the final EOI marker. In the current implementation, half a dozen bytes should suffice for this, but for safety's sake we recommend ensuring that at least 100 bytes are free before calling jpeg_finish_compress(). Furthermore, since jpeg_finish_compress() cannot suspend, you cannot request multi-pass operating modes such as Huffman code optimization or multiple-scan output. That would imply that a large amount of data would be written inside jpeg_finish_compress(), which would certainly trigger a buffer overrun. Decompression suspension: For decompression suspension, use a fill_input_buffer() routine that returns FALSE (except perhaps during error recovery, as discussed below). This will cause the decompressor to return to its caller with an indication that suspension has occurred. This can happen at three places: * jpeg_read_header(): will return JPEG_SUSPENDED. * jpeg_read_scanlines(): will return the number of scanlines already completed (possibly 0). * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE. The surrounding application must recognize these cases, load more data into the input buffer, and repeat the call. In the case of jpeg_read_scanlines(), adjust the passed pointers to reflect any scanlines successfully read. Just as with compression, the decompressor will typically backtrack to a convenient restart point before suspending. The data beyond the current position of next_input_byte/bytes_in_buffer must NOT be discarded; it will be re-read upon resumption. In most implementations, you'll need to shift this data down to the start of your work buffer and then load more data after it. Again, this behavior means that a several-Kbyte work buffer is essential for decent performance; furthermore, you should load a reasonable amount of new data before resuming decompression. (If you loaded, say, only one new byte each time around, you could waste a LOT of cycles.) The skip_input_data() source manager routine requires special care in a suspension scenario. This routine is NOT granted the ability to suspend the decompressor; it can decrement bytes_in_buffer to zero, but no more. If the requested skip distance exceeds the amount of data currently in the input buffer, then skip_input_data() must set bytes_in_buffer to zero and record the additional skip distance somewhere else. The decompressor will immediately call fill_input_buffer(), which will return FALSE, which will cause a suspension return. The surrounding application must then arrange to discard the right number of bytes before it resumes loading the input buffer. (Yes, this design is rather baroque, but it avoids complexity in the far more common case where a non-suspending source manager is used.) If the input data has been exhausted, we recommend that you emit a warning and insert dummy EOI markers just as a non-suspending data source manager would do. This can be handled either in the surrounding application logic or within fill_input_buffer(); the latter is probably more efficient. If fill_input_buffer() knows that no more data is available, it can set the pointer/count to point to a dummy EOI marker and then return TRUE just as if it had read more data in a non-suspending situation. The decompressor does not support suspension within jpeg_start_decompress(). This means that you cannot use suspension with any multi-pass processing mode (eg, two-pass color quantization or multiple-scan JPEG files). In single-pass modes, jpeg_start_decompress() reads no data and thus need never suspend. The decompressor does not attempt to suspend within any JPEG marker; it will backtrack to the start of the marker. Hence the input buffer must be large enough to hold the longest marker in the file. We recommend at least a 2K buffer. The buffer would need to be 64K to allow for arbitrary COM or APPn markers, but the decompressor does not actually try to read these; it just skips them by calling skip_input_data(). If you provide a special marker handling routine that does look at these markers, coping with buffer overflow is your problem. Ordinary JPEG markers should normally not exceed a few hundred bytes each (DHT tables are typically the longest). For robustness against damaged marker length counts, you may wish to insert a test in your application for the case that the input buffer is completely full and yet the decoder has suspended without consuming any data --- otherwise, if this situation did occur, it would lead to an endless loop. Abbreviated datastreams and multiple images ------------------------------------------- A JPEG compression or decompression object can be reused to process multiple images. This saves a small amount of time per image by eliminating the "create" and "destroy" operations, but that isn't the real purpose of the feature. Rather, reuse of an object provides support for abbreviated JPEG datastreams. Object reuse can also simplify processing a series of images in a single input or output file. This section explains these features. A JPEG file normally contains several hundred bytes worth of quantization and Huffman tables. In a situation where many images will be stored or transmitted with identical tables, this may represent an annoying overhead. The JPEG standard therefore permits tables to be omitted. The standard defines three classes of JPEG datastreams: * "Interchange" datastreams contain an image and all tables needed to decode the image. These are the usual kind of JPEG file. * "Abbreviated image" datastreams contain an image, but are missing some or all of the tables needed to decode that image. * "Abbreviated table specification" (henceforth "tables-only") datastreams contain only table specifications. To decode an abbreviated image, it is necessary to load the missing table(s) into the decoder beforehand. This can be accomplished by reading a separate tables-only file. A variant scheme uses a series of images in which the first image is an interchange (complete) datastream, while subsequent ones are abbreviated and rely on the tables loaded by the first image. It is assumed that once the decoder has read a table, it will remember that table until a new definition for the same table number is encountered. It is the application designer's responsibility to figure out how to associate the correct tables with an abbreviated image. While abbreviated datastreams can be useful in a closed environment, their use is strongly discouraged in any situation where data exchange with other applications might be needed. Caveat designer. The JPEG library provides support for reading and writing any combination of tables-only datastreams and abbreviated images. In both compression and decompression objects, a quantization or Huffman table will be retained for the lifetime of the object, unless it is overwritten by a new table definition. To create abbreviated image datastreams, it is only necessary to tell the compressor not to emit some or all of the tables it is using. Each quantization and Huffman table struct contains a boolean field "sent_table", which normally is initialized to FALSE. For each table used by the image, the header-writing process emits the table and sets sent_table = TRUE unless it is already TRUE. (In normal usage, this prevents outputting the same table definition multiple times, as would otherwise occur because the chroma components typically share tables.) Thus, setting this field to TRUE before calling jpeg_start_compress() will prevent the table from being written at all. If you want to create a "pure" abbreviated image file containing no tables, just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the tables. If you want to emit some but not all tables, you'll need to set the individual sent_table fields directly. To create an abbreviated image, you must also call jpeg_start_compress() with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress() will force all the sent_table fields to FALSE. (This is a safety feature to prevent abbreviated images from being created accidentally.) To create a tables-only file, perform the same parameter setup that you normally would, but instead of calling jpeg_start_compress() and so on, call jpeg_write_tables(&cinfo). This will write an abbreviated datastream containing only SOI, DQT and/or DHT markers, and EOI. All the quantization and Huffman tables that are currently defined in the compression object will be emitted unless their sent_tables flag is already TRUE, and all the sent_tables flags will be set TRUE. A sure-fire way to create matching tables-only and abbreviated image files is to proceed as follows: create JPEG compression object set JPEG parameters set destination to tables-only file jpeg_write_tables(&cinfo); set destination to image file jpeg_start_compress(&cinfo, FALSE); write data... jpeg_finish_compress(&cinfo); Since the JPEG parameters are not altered between writing the table file and the abbreviated image file, the same tables are sure to be used. Of course, you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence many times to produce many abbreviated image files matching the table file. You cannot suppress output of the computed Huffman tables if Huffman optimization is selected. (If you could, there'd be no way to decode the image...) Generally, you don't want to set optimize_coding = TRUE when you are trying to produce abbreviated files. In some cases you might want to compress an image using tables which are not stored in the application, but are defined in an interchange or tables-only file readable by the application. This can be done by setting up a JPEG decompression object to read the specification file, then copying the tables into your compression object. To read abbreviated image files, you simply need to load the proper tables into the decompression object before trying to read the abbreviated image. If the proper tables are stored in the application program, you can just allocate the table structs and fill in their contents directly. More commonly you'd want to read the tables from a tables-only file. The jpeg_read_header() call is sufficient to read a tables-only file. You must pass a second parameter of FALSE to indicate that you do not require an image to be present. Thus, the typical scenario is create JPEG decompression object set source to tables-only file jpeg_read_header(&cinfo, FALSE); set source to abbreviated image file jpeg_read_header(&cinfo, TRUE); set decompression parameters jpeg_start_decompress(&cinfo); read data... jpeg_finish_decompress(&cinfo); In some cases, you may want to read a file without knowing whether it contains an image or just tables. In that case, pass FALSE and check the return value from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found, JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value, JPEG_SUSPENDED, is possible when using a suspending data source manager.) Note that jpeg_read_header() will not complain if you read an abbreviated image for which you haven't loaded the missing tables; the missing-table check occurs in jpeg_start_decompress(). It is possible to read a series of images from a single source file by repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence, without releasing/recreating the JPEG object or the data source module. (If you did reinitialize, any partial bufferload left in the data source buffer at the end of one image would be discarded, causing you to lose the start of the next image.) When you use this method, stored tables are automatically carried forward, so some of the images can be abbreviated images that depend on tables from earlier images. If you intend to write a series of images into a single destination file, you might want to make a specialized data destination module that doesn't flush the output buffer at term_destination() time. This would speed things up by some trifling amount. Of course, you'd need to remember to flush the buffer after the last image. You can make the later images be abbreviated ones by passing FALSE to jpeg_start_compress(). Special markers --------------- [to be written ... API needs thought] Downsampled image data ---------------------- [to be written --- not yet implemented anyway] Progress monitoring ------------------- [to be written --- not yet implemented in v5 anyway] Memory management ----------------- This section covers some key facts about the JPEG library's built-in memory manager. For more info, please read structure.doc's section about the memory manager, and consult the source code if necessary. All memory and temporary file allocation within the library is done via the memory manager. If necessary, you can replace the "back end" of the memory manager to control allocation yourself (for example, if you don't want the library to use malloc() and free() for some reason). Some data is allocated "permanently" and will not be freed until the JPEG object is destroyed. Most data is allocated "per image" and is freed by jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the memory manager yourself to allocate structures that will automatically be freed at these times. Typical code for this is ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size); Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object. Use alloc_large instead of alloc_small for anything bigger than a few Kbytes. There are also alloc_sarray and alloc_barray routines that automatically build 2-D sample or block arrays. The library's minimum space requirements to process an image depend on the image's width, but not on its height, because the library ordinarily works with "strip" buffers that are as wide as the image but just a few rows high. Some operating modes (eg, two-pass color quantization) require full-image buffers. Such buffers are treated as "virtual arrays": only the current strip need be in memory, and the rest can be swapped out to a temporary file. If you use the simplest memory manager back end (jmemnobs.c), then no temporary files are used; virtual arrays are simply malloc()'d. Images bigger than memory can be processed only if your system supports virtual memory. The other memory manager back ends support temporary files of various flavors and thus work in machines without virtual memory. They may also be useful on Unix machines if you need to process images that exceed available swap space. When using temporary files, the library will make the in-memory buffers for its virtual arrays just big enough to stay within a "maximum memory" setting. Your application can set this limit by setting cinfo->mem->max_memory_to_use after creating the JPEG object. (Of course, there is still a minimum size for the buffers, so the max-memory setting is effective only if it is bigger than the minimum space needed.) If you allocate any large structures yourself, you must allocate them before jpeg_start_compress() or jpeg_start_decompress() in order to have them counted against the max memory limit. Also keep in mind that space allocated with alloc_small() is ignored, on the assumption that it's too small to be worth worrying about. If you use the jmemname.c or jmemdos.c memory manager back end, it is important to clean up the JPEG object properly to ensure that the temporary files get deleted. (This is especially crucial with jmemdos.c, where the "temporary files" may be extended-memory segments; if they are not freed, DOS will require a reboot to recover the memory.) Thus, with these memory managers, it's a good idea to provide a signal handler that will trap any early exit from your program. The handler should call either jpeg_abort() or jpeg_destroy() for any active JPEG objects. A handler is not needed with jmemnobs.c, and shouldn't be necessary with jmemansi.c either, since the C library is supposed to take care of deleting files made with tmpfile(). Library compile-time options ---------------------------- A number of compile-time options are available by modifying jmorecfg.h. The JPEG standard provides for both the baseline 8-bit DCT process and a 12-bit DCT process. 12-bit lossy JPEG is supported if you define BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be larger than a char, so it affects the surrounding application's image data. At present, a 12-bit library can handle *only* 12-bit images, not both precisions. The maximum number of components (color channels) in the image is determined by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we expect that few applications will need more than four or so. On machines with unusual data type sizes, you may be able to improve performance or reduce memory space by tweaking the various typedefs in jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s is quite slow; consider trading memory for speed by making JCOEF, INT16, and UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int. You probably don't want to make JSAMPLE be int unless you have lots of memory to burn. You can reduce the size of the library by compiling out various optional functions. To do this, undefine xxx_SUPPORTED symbols as necessary. Portability considerations -------------------------- The JPEG library has been written to be extremely portable; the sample applications cjpeg and djpeg are slightly less so. This section summarizes the design goals in this area. (If you encounter any bugs that cause the library to be less portable than is claimed here, we'd appreciate hearing about them.) The code works fine on both ANSI and pre-ANSI C compilers, using any of the popular system include file setups, and some not-so-popular ones too. See install.doc for configuration procedures. The code is not dependent on the exact sizes of the C data types. As distributed, we make the assumptions that char is at least 8 bits wide short is at least 16 bits wide int is at least 16 bits wide long is at least 32 bits wide (These are the minimum requirements of the ANSI C standard.) Wider types will work fine, although memory may be used inefficiently if char is much larger than 8 bits or short is much bigger than 16 bits. The code should work equally well with 16- or 32-bit ints. In a system where these assumptions are not met, you may be able to make the code work by modifying the typedefs in jmorecfg.h. However, you will probably have difficulty if int is less than 16 bits wide, since references to plain int abound in the code. char can be either signed or unsigned, although the code runs faster if an unsigned char type is available. If char is wider than 8 bits, you will need to redefine JOCTET and/or provide custom data source/destination managers so that JOCTET represents exactly 8 bits of data on external storage. The JPEG library proper does not assume ASCII representation of characters. But some of the image file I/O modules in cjpeg/djpeg do have ASCII dependencies in file-header manipulation; so does cjpeg's select_file_type() routine. The JPEG library does not rely heavily on the C library. In particular, C stdio is used only by the data source/destination modules and the error handler, all of which are application-replaceable. (cjpeg/djpeg are more heavily dependent on stdio.) malloc and free are called only from the memory manager "back end" module, so you can use a different memory allocator by replacing that one file. The code generally assumes that C names must be unique in the first 15 characters. However, global function names can be made unique in the first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES. More info about porting the code may be gleaned by reading jconfig.doc, jmorecfg.h, and jinclude.h. Notes for MS-DOS implementors ----------------------------- The JPEG code is designed to be compiled with 80x86 "small" or "medium" memory models (i.e., data pointers are 16 bits unless explicitly declared "far"; code pointers can be either size). You should be able to use small model to compile cjpeg or djpeg by itself, but you will probably have to go to medium model if you include the JPEG code in a larger application. This shouldn't hurt performance much. You *will* take a noticeable performance hit if you compile in a large-data memory model, and you should avoid "huge" model if at all possible. Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use a small-data model; be sure it is NOT defined if you use a large-data or flat memory model. [The following space estimates are out of date and need to be recalculated.] An 8K stack is much more than sufficient for the JPEG code. When executed, it will typically malloc about 10K-20K worth of near heap space (and lots of far heap, but that doesn't count in this calculation). This figure will vary depending on image size and other factors, but figuring 30K should be more than sufficient. Thus you have about 25K available for static data and other modules' near heap requirements before you need to go to a larger memory model. The C library's static data will account for several K of this, but that still leaves a good deal for your needs. (If you are tight on space, you could reduce the sizes of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to 1K.) Far data space may also be a tight resource when you are dealing with large images. The most memory-intensive case is decompression with two-pass color quantization, or single-pass quantization to an externally supplied color map. This requires a 128Kb color lookup table plus strip buffers amounting to about 150 bytes per column for typical sampling ratios (eg, about 96000 bytes for a 640-pixel-wide image). You may not be able to process wide images if you have large data structures of your own. Of course, all of these concerns vanish if you use a flat-memory-model 386 compiler such as DJGPP or Watcom C. We highly recommend flat model if you can use it; the JPEG library is significantly faster in flat model. \ No newline at end of file diff --git a/Independent JPEG Group/makcjpeg.st b/Independent JPEG Group/makcjpeg.st new file mode 100644 index 0000000..b6c192c --- /dev/null +++ b/Independent JPEG Group/makcjpeg.st @@ -0,0 +1 @@ +; Project file for Independent JPEG Group's software ; ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. ; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de) ; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de). ; ; To use this file, rename it to CJPEG.PRJ. ; If you are using Turbo C, change filenames beginning with "PC..." to "TC..." ; Read installation instructions before trying to make the program! ; ; ; * * * Output file * * * cjpeg.ttp ; ; * * * COMPILER OPTIONS * * * .C[-P] ; absolute calls .C[-M] ; and no string merging, folks .C[-w-par] ; no "parameter xxxx unused" .C[-wsig] ; warn if significant digits may be lost .C[-w-cln] ; no "constant is long" warnings = ; * * * * List of modules * * * * PCSTART.O cjpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,jversion.h) rdppm.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) rdgif.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) rdtarga.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) LIBJPEG.LIB ; built by LIBJPEG.PRJ ;PCFLTLIB.LIB ; floating point library -- you shouldn't need this PCSTDLIB.LIB ; standard library PCEXTLIB.LIB ; extended library \ No newline at end of file diff --git a/Independent JPEG Group/makdjpeg.st b/Independent JPEG Group/makdjpeg.st new file mode 100644 index 0000000..c579ed9 --- /dev/null +++ b/Independent JPEG Group/makdjpeg.st @@ -0,0 +1 @@ +; Project file for Independent JPEG Group's software ; ; This project file is for Atari ST/STE/TT systems using Pure C or Turbo C. ; Thanks to Frank Moehle (Frank.Moehle@arbi.informatik.uni-oldenburg.de) ; and to Dr. B. Setzepfandt (bernd@gina.uni-muenster.de). ; ; To use this file, rename it to DJPEG.PRJ. ; If you are using Turbo C, change filenames beginning with "PC..." to "TC..." ; Read installation instructions before trying to make the program! ; ; ; * * * Output file * * * djpeg.ttp ; ; * * * COMPILER OPTIONS * * * .C[-P] ; absolute calls .C[-M] ; and no string merging, folks .C[-w-par] ; no "parameter xxxx unused" .C[-wsig] ; warn if significant digits may be lost .C[-w-cln] ; no "constant is long" warnings = ; * * * * List of modules * * * * PCSTART.O djpeg.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h,jversion.h) wrppm.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) wrgif.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) wrtarga.c (cdjpeg.h,jinclude.h,jconfig.h,jpeglib.h,jmorecfg.h,jerror.h,cderror.h) LIBJPEG.LIB ; built by LIBJPEG.PRJ ;PCFLTLIB.LIB ; floating point library -- you shouldn't need this PCSTDLIB.LIB ; standard library PCEXTLIB.LIB ; extended library \ No newline at end of file diff --git a/Independent JPEG Group/makefile.ansi b/Independent JPEG Group/makefile.ansi new file mode 100644 index 0000000..058ba10 --- /dev/null +++ b/Independent JPEG Group/makefile.ansi @@ -0,0 +1 @@ +# Makefile for Independent JPEG Group's software # This makefile is suitable for Unix-like systems with ANSI-capable compilers. # If you have a non-ANSI compiler, makefile.unix is a better starting point. # Read installation instructions before saying "make" !! # The name of your C compiler: CC= cc # You may need to adjust these cc options: CFLAGS= -O # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via -D switches here. # Link-time cc options: LDFLAGS= # To link any special libraries, add the necessary -l commands here. LDLIBS= # Put here the object file name for the correct system-dependent memory # manager file. For Unix this is usually jmemnobs.o, but you may want # to use jmemansi.o or jmemname.o if you have limited swap space. SYSDEPMEM= jmemnobs.o # miscellaneous OS-dependent stuff # linker LN= $(CC) # file deletion command RM= rm -f # library (.a) file creation command AR= ar rc # second step in .a creation (use "touch" if not needed) AR2= ranlib # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapi.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcmainct.c \ jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c \ jdapi.c jdatasrc.c jdatadst.c jdcoefct.c jdcolor.c jddctmgr.c \ jdhuff.c jdmainct.c jdmarker.c jdmaster.c jdpostct.c jdsample.c \ jerror.c jutils.c jfdctllm.c jidctllm.c jidctred.c jquant1.c \ jquant2.c jmemmgr.c jmemansi.c jmemname.c jmemnobs.c jmemdos.c # source files: cjpeg/djpeg applications APPSOURCES= cjpeg.c djpeg.c rdppm.c wrppm.c rdgif.c wrgif.c rdtarga.c \ wrtarga.c SOURCES= $(LIBSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ jpeglib.h jversion.h cdjpeg.h cderror.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 example.c libjpeg.doc \ structure.doc coderules.doc filelist.doc change.log MAKEFILES= configure makefile.auto makefile.ansi makefile.unix \ makefile.manx makefile.sas makcjpeg.st makdjpeg.st makljpeg.st \ makefile.bcc makefile.mc6 makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.auto jconfig.manx jconfig.sas jconfig.st jconfig.bcc \ jconfig.mc6 jconfig.vms OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapi.o jcparam.o jdatadst.o jcmaster.o jcmarker.o jcmainct.o \ jcprepct.o jccoefct.o jccolor.o jcsample.o jchuff.o jcdctmgr.o \ jfdctllm.o # decompression library object files DLIBOBJECTS= jdapi.o jdatasrc.o jdmaster.o jdmarker.o jdmainct.o jdcoefct.o \ jdpostct.o jddctmgr.o jidctllm.o jidctred.o jdhuff.o jdsample.o \ jdcolor.o jquant1.o jquant2.o # These objectfiles are included in libjpeg.a LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for cjpeg and djpeg applications (excluding library files) COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o all: libjpeg.a cjpeg djpeg libjpeg.a: $(LIBOBJECTS) $(RM) libjpeg.a $(AR) libjpeg.a $(LIBOBJECTS) $(AR2) libjpeg.a cjpeg: $(COBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.a $(LDLIBS) djpeg: $(DOBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.a $(LDLIBS) jconfig.h: jconfig.doc echo You must prepare a system-dependent jconfig.h file. echo Please read the installation directions in install.doc. exit 1 clean: $(RM) *.o cjpeg djpeg libjpeg.a core testout.* distribute: $(RM) jpegsrc.tar* tar cvf jpegsrc.tar $(DISTFILES) compress -v jpegsrc.tar test: cjpeg djpeg $(RM) testout.ppm testout.gif testout.jpg ./djpeg -outfile testout.ppm testorig.jpg ./djpeg -gif -outfile testout.gif testorig.jpg ./cjpeg -outfile testout.jpg testimg.ppm cmp testimg.ppm testout.ppm cmp testimg.gif testout.gif cmp testimg.jpg testout.jpg jcapi.o : jcapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.o : jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.o : jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.o : jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.o : jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.o : jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.o : jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.o : jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.o : jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.o : jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcprepct.o : jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.o : jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapi.o : jdapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatasrc.o : jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatadst.o : jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.o : jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.o : jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.o : jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.o : jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.o : jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.o : jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.o : jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdpostct.o : jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.o : jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.o : jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jutils.o : jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jfdctllm.o : jfdctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctllm.o : jidctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.o : jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.o : jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.o : jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.o : jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.o : jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.o : jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.o : jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.o : cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.o : djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h rdppm.o : rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.o : wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.o : rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.o : wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.o : rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.o : wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h \ No newline at end of file diff --git a/Independent JPEG Group/makefile.auto b/Independent JPEG Group/makefile.auto new file mode 100644 index 0000000..3a50a95 --- /dev/null +++ b/Independent JPEG Group/makefile.auto @@ -0,0 +1 @@ +# Makefile for Independent JPEG Group's software # makefile.auto is edited by configure to produce a custom Makefile. # Read installation instructions before saying "make" !! # For compiling with source and object files in different directories. srcdir = @srcdir@ VPATH = @srcdir@ # Where to install the programs and man pages. prefix = /usr/local exec_prefix = $(prefix) bindir = $(exec_prefix)/bin libdir = $(exec_prefix)/lib includedir = $(prefix)/include mandir = $(prefix)/man/man1 binprefix = manprefix = manext = 1 # The name of your C compiler: CC= @CC@ # You may need to adjust these cc options: CFLAGS= -O -I$(srcdir) # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via -D switches here. # However, any special defines for ansi2knr.c may be included here: ANSI2KNRFLAGS= @ANSI2KNRFLAGS@ # Link-time cc options: LDFLAGS= # To link any special libraries, add the necessary -l commands here. LDLIBS= # Put here the object file name for the correct system-dependent memory # manager file. For Unix this is usually jmemnobs.o, but you may want # to use jmemansi.o or jmemname.o if you have limited swap space. SYSDEPMEM= @MEMORYMGR@ # miscellaneous OS-dependent stuff SHELL= /bin/sh # linker LN= $(CC) # file deletion command RM= rm -f # library (.a) file creation command AR= ar rc # second step in .a creation (use "touch" if not needed) AR2= @RANLIB@ # installation program INSTALL= @INSTALL@ INSTALL_PROGRAM= @INSTALL_PROGRAM@ INSTALL_DATA= @INSTALL_DATA@ # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapi.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcmainct.c \ jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c \ jdapi.c jdatasrc.c jdatadst.c jdcoefct.c jdcolor.c jddctmgr.c \ jdhuff.c jdmainct.c jdmarker.c jdmaster.c jdpostct.c jdsample.c \ jerror.c jutils.c jfdctllm.c jidctllm.c jidctred.c jquant1.c \ jquant2.c jmemmgr.c jmemansi.c jmemname.c jmemnobs.c jmemdos.c # source files: cjpeg/djpeg applications APPSOURCES= cjpeg.c djpeg.c rdppm.c wrppm.c rdgif.c wrgif.c rdtarga.c \ wrtarga.c SOURCES= $(LIBSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ jpeglib.h jversion.h cdjpeg.h cderror.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 example.c libjpeg.doc \ structure.doc coderules.doc filelist.doc change.log MAKEFILES= configure makefile.auto makefile.ansi makefile.unix \ makefile.manx makefile.sas makcjpeg.st makdjpeg.st makljpeg.st \ makefile.bcc makefile.mc6 makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.auto jconfig.manx jconfig.sas jconfig.st jconfig.bcc \ jconfig.mc6 jconfig.vms OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapi.o jcparam.o jdatadst.o jcmaster.o jcmarker.o jcmainct.o \ jcprepct.o jccoefct.o jccolor.o jcsample.o jchuff.o jcdctmgr.o \ jfdctllm.o # decompression library object files DLIBOBJECTS= jdapi.o jdatasrc.o jdmaster.o jdmarker.o jdmainct.o jdcoefct.o \ jdpostct.o jddctmgr.o jidctllm.o jidctred.o jdhuff.o jdsample.o \ jdcolor.o jquant1.o jquant2.o # These objectfiles are included in libjpeg.a LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for cjpeg and djpeg applications (excluding library files) COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o all: @ANSI2KNR@ libjpeg.a cjpeg djpeg # This rule causes ansi2knr to be invoked. @ISANSICOM@.c.o: @ISANSICOM@ ./ansi2knr $(srcdir)/$*.c T$*.c @ISANSICOM@ $(CC) $(CFLAGS) -o $*.o -c T$*.c @ISANSICOM@ $(RM) T$*.c ansi2knr: ansi2knr.c $(CC) $(CFLAGS) $(ANSI2KNRFLAGS) -o ansi2knr ansi2knr.c libjpeg.a: @ANSI2KNR@ $(LIBOBJECTS) $(RM) libjpeg.a $(AR) libjpeg.a $(LIBOBJECTS) $(AR2) libjpeg.a cjpeg: @ANSI2KNR@ $(COBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.a $(LDLIBS) djpeg: @ANSI2KNR@ $(DOBJECTS) libjpeg.a $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.a $(LDLIBS) jconfig.h: jconfig.doc echo You must prepare a system-dependent jconfig.h file. echo Please read the installation directions in install.doc. exit 1 install: cjpeg djpeg $(INSTALL_PROGRAM) cjpeg $(bindir)/$(binprefix)cjpeg $(INSTALL_PROGRAM) djpeg $(bindir)/$(binprefix)djpeg $(INSTALL_DATA) $(srcdir)/cjpeg.1 $(mandir)/$(manprefix)cjpeg.$(manext) $(INSTALL_DATA) $(srcdir)/djpeg.1 $(mandir)/$(manprefix)djpeg.$(manext) install-lib: libjpeg.a jconfig.h $(INSTALL_DATA) libjpeg.a $(libdir)/$(binprefix)libjpeg.a $(INSTALL_DATA) jconfig.h $(includedir)/jconfig.h $(INSTALL_DATA) $(srcdir)/jpeglib.h $(includedir)/jpeglib.h $(INSTALL_DATA) $(srcdir)/jmorecfg.h $(includedir)/jmorecfg.h $(INSTALL_DATA) $(srcdir)/jerror.h $(includedir)/jerror.h clean: $(RM) *.o cjpeg djpeg libjpeg.a ansi2knr core testout.* distribute: $(RM) jpegsrc.tar* tar cvf jpegsrc.tar $(DISTFILES) compress -v jpegsrc.tar test: cjpeg djpeg $(RM) testout.ppm testout.gif testout.jpg ./djpeg -outfile testout.ppm testorig.jpg ./djpeg -gif -outfile testout.gif testorig.jpg ./cjpeg -outfile testout.jpg testimg.ppm cmp testimg.ppm testout.ppm cmp testimg.gif testout.gif cmp testimg.jpg testout.jpg check: test jcapi.o : jcapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.o : jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.o : jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.o : jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.o : jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.o : jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.o : jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.o : jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.o : jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.o : jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcprepct.o : jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.o : jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapi.o : jdapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatasrc.o : jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatadst.o : jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.o : jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.o : jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.o : jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.o : jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.o : jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.o : jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.o : jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdpostct.o : jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.o : jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.o : jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jutils.o : jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jfdctllm.o : jfdctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctllm.o : jidctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.o : jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.o : jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.o : jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.o : jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.o : jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.o : jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.o : jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.o : cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.o : djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h rdppm.o : rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.o : wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.o : rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.o : wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.o : rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.o : wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h \ No newline at end of file diff --git a/Independent JPEG Group/makefile.bcc b/Independent JPEG Group/makefile.bcc new file mode 100644 index 0000000..f7ef9c2 --- /dev/null +++ b/Independent JPEG Group/makefile.bcc @@ -0,0 +1 @@ +# Makefile for Independent JPEG Group's software # This makefile is suitable for Borland C (Turbo C) on MS-DOS. # It is set up for Borland C++, revision 3.0 or later. # For older versions (pre-3.0), replace "-O2" with "-O -G -Z" in CFLAGS. # If you have an even older version of Turbo C, you may be able to make it # work by saying "CC= tcc" below. (Very early versions of Turbo C++, # like 1.01, are so buggy that you may as well forget it.) # Thanks to Tom Wright and Ge' Weijers for this file. # Read installation instructions before saying "make" !! # The name of your C compiler: CC= bcc # You may need to adjust these cc options: CFLAGS= -ms -w-par -O2 # -ms selects small memory model for most efficient code # -w-par suppresses warnings about unused function parameters # -O2 enables full code optimization (for pre-3.0 Borland C++, use -O -G -Z) # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via -D switches here. # Link-time cc options: LDFLAGS= -ms # memory model option here must match CFLAGS! # Put here the object file name for the correct system-dependent memory # manager file. For DOS, we recommend jmemdos.c and jmemdosa.asm. SYSDEPMEM= jmemdos.obj jmemdosa.obj # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapi.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcmainct.c \ jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c \ jdapi.c jdatasrc.c jdatadst.c jdcoefct.c jdcolor.c jddctmgr.c \ jdhuff.c jdmainct.c jdmarker.c jdmaster.c jdpostct.c jdsample.c \ jerror.c jutils.c jfdctllm.c jidctllm.c jidctred.c jquant1.c \ jquant2.c jmemmgr.c jmemansi.c jmemname.c jmemnobs.c jmemdos.c # source files: cjpeg/djpeg applications APPSOURCES= cjpeg.c djpeg.c rdppm.c wrppm.c rdgif.c wrgif.c rdtarga.c \ wrtarga.c SOURCES= $(LIBSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ jpeglib.h jversion.h cdjpeg.h cderror.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 example.c libjpeg.doc \ structure.doc coderules.doc filelist.doc change.log MAKEFILES= configure makefile.auto makefile.ansi makefile.unix \ makefile.manx makefile.sas makcjpeg.st makdjpeg.st makljpeg.st \ makefile.bcc makefile.mc6 makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.auto jconfig.manx jconfig.sas jconfig.st jconfig.bcc \ jconfig.mc6 jconfig.vms OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapi.obj jcparam.obj jdatadst.obj jcmaster.obj jcmarker.obj \ jcmainct.obj jcprepct.obj jccoefct.obj jccolor.obj jcsample.obj \ jchuff.obj jcdctmgr.obj jfdctllm.obj # decompression library object files DLIBOBJECTS= jdapi.obj jdatasrc.obj jdmaster.obj jdmarker.obj jdmainct.obj \ jdcoefct.obj jdpostct.obj jddctmgr.obj jidctllm.obj jidctred.obj \ jdhuff.obj jdsample.obj jdcolor.obj jquant1.obj jquant2.obj # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for cjpeg and djpeg applications (excluding library files) COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj # need linker response file because file list > 128 chars RFILE= libjpeg.ans all: libjpeg.lib cjpeg.exe djpeg.exe libjpeg.lib: $(LIBOBJECTS) $(RFILE) del libjpeg.lib tlib @$(RFILE) # linker response file for building libjpeg.lib $(RFILE) : Makefile del $(RFILE) echo libjpeg.lib & >$(RFILE) echo +jcapi.obj +jcparam.obj +jdatadst.obj +jcmaster.obj & >>$(RFILE) echo +jcmarker.obj +jcmainct.obj +jcprepct.obj +jccoefct.obj & >>$(RFILE) echo +jccolor.obj +jcsample.obj +jchuff.obj +jcdctmgr.obj & >>$(RFILE) echo +jfdctllm.obj +jdapi.obj +jdatasrc.obj +jdmaster.obj & >>$(RFILE) echo +jdmarker.obj +jdmainct.obj +jdcoefct.obj +jdpostct.obj & >>$(RFILE) echo +jddctmgr.obj +jidctllm.obj +jidctred.obj +jdhuff.obj & >>$(RFILE) echo +jdsample.obj +jdcolor.obj +jquant1.obj +jquant2.obj & >>$(RFILE) echo +jcomapi.obj +jutils.obj +jerror.obj +jmemmgr.obj & >>$(RFILE) echo +jmemdos.obj +jmemdosa.obj >>$(RFILE) cjpeg.exe: $(COBJECTS) libjpeg.lib $(CC) $(LDFLAGS) -ecjpeg.exe $(COBJECTS) libjpeg.lib djpeg.exe: $(DOBJECTS) libjpeg.lib $(CC) $(LDFLAGS) -edjpeg.exe $(DOBJECTS) libjpeg.lib .c.obj: $(CC) $(CFLAGS) -c $< jconfig.h: jconfig.doc echo You must prepare a system-dependent jconfig.h file. echo Please read the installation directions in install.doc. exit 1 clean: del *.obj del libjpeg.lib del cjpeg.exe del djpeg.exe del testout.* test: cjpeg.exe djpeg.exe del testout.* djpeg -outfile testout.ppm testorig.jpg djpeg -gif -outfile testout.gif testorig.jpg cjpeg -outfile testout.jpg testimg.ppm fc /b testimg.ppm testout.ppm fc /b testimg.gif testout.gif fc /b testimg.jpg testout.jpg jcapi.obj : jcapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.obj : jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.obj : jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.obj : jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.obj : jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.obj : jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.obj : jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.obj : jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.obj : jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcprepct.obj : jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.obj : jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapi.obj : jdapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatasrc.obj : jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatadst.obj : jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.obj : jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.obj : jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.obj : jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.obj : jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdpostct.obj : jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.obj : jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.obj : jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jutils.obj : jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jfdctllm.obj : jfdctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctllm.obj : jidctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.obj : jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.obj : jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.obj : jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.obj : jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.obj : jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.obj : jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.obj : jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.obj : cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.obj : djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h rdppm.obj : rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.obj : wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.obj : rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.obj : wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.obj : rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.obj : wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jmemdosa.obj : jmemdosa.asm tasm /mx jmemdosa.asm \ No newline at end of file diff --git a/Independent JPEG Group/makefile.manx b/Independent JPEG Group/makefile.manx new file mode 100644 index 0000000..89e5530 --- /dev/null +++ b/Independent JPEG Group/makefile.manx @@ -0,0 +1 @@ +# Makefile for Independent JPEG Group's software # This makefile is for Amiga systems using Manx Aztec C ver 5.x. # Thanks to D.J. James (djjames@cup.portal.com) for this version. # Read installation instructions before saying "make" !! # The name of your C compiler: CC= cc # You may need to adjust these cc options: # Uncomment for generic 68000 code (will work on any Amiga) ARCHFLAGS= -sn # Uncomment for 68020/68030 code (faster, but won't run on 68000 CPU) #ARCHFLAGS= -c2 CFLAGS= -MC -MD $(ARCHFLAGS) -spfam -r4 # Link-time cc options: LDFLAGS= -g # To link any special libraries, add the necessary -l commands here. LDLIBS= -lml -lcl # Put here the object file name for the correct system-dependent memory # manager file. For Amiga we recommend jmemname.o. SYSDEPMEM= jmemname.o # miscellaneous OS-dependent stuff # linker LN= ln # file deletion command RM= delete quiet # library (.lib) file creation command AR= lb # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapi.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcmainct.c \ jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c \ jdapi.c jdatasrc.c jdatadst.c jdcoefct.c jdcolor.c jddctmgr.c \ jdhuff.c jdmainct.c jdmarker.c jdmaster.c jdpostct.c jdsample.c \ jerror.c jutils.c jfdctllm.c jidctllm.c jidctred.c jquant1.c \ jquant2.c jmemmgr.c jmemansi.c jmemname.c jmemnobs.c jmemdos.c # source files: cjpeg/djpeg applications APPSOURCES= cjpeg.c djpeg.c rdppm.c wrppm.c rdgif.c wrgif.c rdtarga.c \ wrtarga.c SOURCES= $(LIBSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ jpeglib.h jversion.h cdjpeg.h cderror.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 example.c libjpeg.doc \ structure.doc coderules.doc filelist.doc change.log MAKEFILES= configure makefile.auto makefile.ansi makefile.unix \ makefile.manx makefile.sas makcjpeg.st makdjpeg.st makljpeg.st \ makefile.bcc makefile.mc6 makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.auto jconfig.manx jconfig.sas jconfig.st jconfig.bcc \ jconfig.mc6 jconfig.vms OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapi.o jcparam.o jdatadst.o jcmaster.o jcmarker.o jcmainct.o \ jcprepct.o jccoefct.o jccolor.o jcsample.o jchuff.o jcdctmgr.o \ jfdctllm.o # decompression library object files DLIBOBJECTS= jdapi.o jdatasrc.o jdmaster.o jdmarker.o jdmainct.o jdcoefct.o \ jdpostct.o jddctmgr.o jidctllm.o jidctred.o jdhuff.o jdsample.o \ jdcolor.o jquant1.o jquant2.o # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for cjpeg and djpeg applications (excluding library files) COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o all: libjpeg.lib cjpeg djpeg libjpeg.lib: $(LIBOBJECTS) -$(RM) libjpeg.lib $(AR) libjpeg.lib $(LIBOBJECTS) cjpeg: $(COBJECTS) libjpeg.lib $(LN) $(LDFLAGS) -o cjpeg $(COBJECTS) libjpeg.lib $(LDLIBS) djpeg: $(DOBJECTS) libjpeg.lib $(LN) $(LDFLAGS) -o djpeg $(DOBJECTS) libjpeg.lib $(LDLIBS) jconfig.h: jconfig.doc echo You must prepare a system-dependent jconfig.h file. echo Please read the installation directions in install.doc. exit 1 clean: -$(RM) *.o cjpeg djpeg libjpeg.lib core testout.* test: cjpeg djpeg -$(RM) testout.ppm testout.gif testout.jpg djpeg -outfile testout.ppm testorig.jpg djpeg -gif -outfile testout.gif testorig.jpg cjpeg -outfile testout.jpg testimg.ppm cmp testimg.ppm testout.ppm cmp testimg.gif testout.gif cmp testimg.jpg testout.jpg jcapi.o : jcapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.o : jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.o : jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.o : jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.o : jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.o : jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.o : jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.o : jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.o : jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.o : jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcprepct.o : jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.o : jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapi.o : jdapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatasrc.o : jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatadst.o : jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.o : jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.o : jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.o : jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.o : jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.o : jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.o : jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.o : jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdpostct.o : jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.o : jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.o : jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jutils.o : jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jfdctllm.o : jfdctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctllm.o : jidctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.o : jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.o : jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.o : jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.o : jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.o : jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.o : jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.o : jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.o : jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.o : cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.o : djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h rdppm.o : rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.o : wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.o : rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.o : wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.o : rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.o : wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h \ No newline at end of file diff --git a/Independent JPEG Group/makefile.mc6 b/Independent JPEG Group/makefile.mc6 new file mode 100644 index 0000000..4ad6af6 --- /dev/null +++ b/Independent JPEG Group/makefile.mc6 @@ -0,0 +1 @@ +# Makefile for Independent JPEG Group's software # This makefile is for Microsoft C for MS-DOS, version 6.00A and up. # Use NMAKE, not Microsoft's brain-damaged MAKE. # Thanks to Alan Wright and Chris Turner of Olivetti Research Ltd. # Read installation instructions before saying "nmake" !! # You may need to adjust these compiler options: CFLAGS = -AS -Oecigt -Gs -W3 # -AS small memory model (or use -AM for medium model) # -Oecigt -Gs maximum safe optimisation (-Ol has bugs in MSC 6.00A) # -W3 warning level 3 # You might also want to add -G2 if you have an 80286, etc. # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via -D switches here. # Put here the object file name for the correct system-dependent memory # manager file. For DOS, we recommend jmemdos.c and jmemdosa.asm. SYSDEPMEM= jmemdos.obj jmemdosa.obj # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapi.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcmainct.c \ jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c \ jdapi.c jdatasrc.c jdatadst.c jdcoefct.c jdcolor.c jddctmgr.c \ jdhuff.c jdmainct.c jdmarker.c jdmaster.c jdpostct.c jdsample.c \ jerror.c jutils.c jfdctllm.c jidctllm.c jidctred.c jquant1.c \ jquant2.c jmemmgr.c jmemansi.c jmemname.c jmemnobs.c jmemdos.c # source files: cjpeg/djpeg applications APPSOURCES= cjpeg.c djpeg.c rdppm.c wrppm.c rdgif.c wrgif.c rdtarga.c \ wrtarga.c SOURCES= $(LIBSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ jpeglib.h jversion.h cdjpeg.h cderror.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 example.c libjpeg.doc \ structure.doc coderules.doc filelist.doc change.log MAKEFILES= configure makefile.auto makefile.ansi makefile.unix \ makefile.manx makefile.sas makcjpeg.st makdjpeg.st makljpeg.st \ makefile.bcc makefile.mc6 makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.auto jconfig.manx jconfig.sas jconfig.st jconfig.bcc \ jconfig.mc6 jconfig.vms OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapi.obj jcparam.obj jdatadst.obj jcmaster.obj jcmarker.obj \ jcmainct.obj jcprepct.obj jccoefct.obj jccolor.obj jcsample.obj \ jchuff.obj jcdctmgr.obj jfdctllm.obj # decompression library object files DLIBOBJECTS= jdapi.obj jdatasrc.obj jdmaster.obj jdmarker.obj jdmainct.obj \ jdcoefct.obj jdpostct.obj jddctmgr.obj jidctllm.obj jidctred.obj \ jdhuff.obj jdsample.obj jdcolor.obj jquant1.obj jquant2.obj # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for cjpeg and djpeg applications (excluding library files) COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj # need linker response file because file list > 128 chars RFILE = libjpeg.ans all: libjpeg.lib cjpeg.exe djpeg.exe libjpeg.lib: $(LIBOBJECTS) $(RFILE) del libjpeg.lib lib @$(RFILE) ; # linker response file for building libjpeg.lib $(RFILE) : Makefile del $(RFILE) echo libjpeg.lib >$(RFILE) # silly want-to-create-it prompt: echo y >>$(RFILE) echo +jcapi.obj +jcparam.obj +jdatadst.obj +jcmaster.obj & >>$(RFILE) echo +jcmarker.obj +jcmainct.obj +jcprepct.obj +jccoefct.obj & >>$(RFILE) echo +jccolor.obj +jcsample.obj +jchuff.obj +jcdctmgr.obj & >>$(RFILE) echo +jfdctllm.obj +jdapi.obj +jdatasrc.obj +jdmaster.obj & >>$(RFILE) echo +jdmarker.obj +jdmainct.obj +jdcoefct.obj +jdpostct.obj & >>$(RFILE) echo +jddctmgr.obj +jidctllm.obj +jidctred.obj +jdhuff.obj & >>$(RFILE) echo +jdsample.obj +jdcolor.obj +jquant1.obj +jquant2.obj & >>$(RFILE) echo +jcomapi.obj +jutils.obj +jerror.obj +jmemmgr.obj & >>$(RFILE) echo +jmemdos.obj +jmemdosa.obj >>$(RFILE) cjpeg.exe: $(COBJECTS) libjpeg.lib link /STACK:4096 /EXEPACK $(COBJECTS), cjpeg.exe, , libjpeg.lib, ; djpeg.exe: $(DOBJECTS) libjpeg.lib link /STACK:4096 /EXEPACK $(DOBJECTS), djpeg.exe, , libjpeg.lib, ; jconfig.h: jconfig.doc echo You must prepare a system-dependent jconfig.h file. echo Please read the installation directions in install.doc. exit 1 clean: del *.obj del libjpeg.lib del cjpeg.exe del djpeg.exe del testout.* test: cjpeg.exe djpeg.exe del testout.* djpeg -outfile testout.ppm testorig.jpg djpeg -gif -outfile testout.gif testorig.jpg cjpeg -outfile testout.jpg testimg.ppm fc /b testimg.ppm testout.ppm fc /b testimg.gif testout.gif fc /b testimg.jpg testout.jpg jcapi.obj : jcapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.obj : jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.obj : jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.obj : jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.obj : jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.obj : jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.obj : jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.obj : jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.obj : jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcprepct.obj : jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.obj : jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapi.obj : jdapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatasrc.obj : jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatadst.obj : jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.obj : jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.obj : jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.obj : jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.obj : jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdpostct.obj : jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.obj : jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.obj : jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jutils.obj : jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jfdctllm.obj : jfdctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctllm.obj : jidctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.obj : jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.obj : jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.obj : jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.obj : jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.obj : jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.obj : jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.obj : jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.obj : cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.obj : djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h rdppm.obj : rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.obj : wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.obj : rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.obj : wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.obj : rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.obj : wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jmemdosa.obj : jmemdosa.asm masm /mx $*; \ No newline at end of file diff --git a/Independent JPEG Group/makefile.mms b/Independent JPEG Group/makefile.mms new file mode 100644 index 0000000..850c569 --- /dev/null +++ b/Independent JPEG Group/makefile.mms @@ -0,0 +1 @@ +# Makefile for Independent JPEG Group's software # This makefile is for use with MMS on VAX/VMS systems. # Thanks to Rick Dyson (dyson@iowasp.physics.uiowa.edu) # and Tim Bell (tbell@netcom.com) for their help. # Read installation instructions before saying "MMS" !! # You may need to adjust these cc options: CFLAGS= $(CFLAGS) /NoDebug /Optimize # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via /Define switches here. OPT= Sys$Disk:[]MAKVMS.OPT # Put here the object file name for the correct system-dependent memory # manager file. For Unix this is usually jmemnobs.o, but you may want # to use jmemansi.o or jmemname.o if you have limited swap space. SYSDEPMEM= jmemnobs.obj # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapi.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcmainct.c \ jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c \ jdapi.c jdatasrc.c jdatadst.c jdcoefct.c jdcolor.c jddctmgr.c \ jdhuff.c jdmainct.c jdmarker.c jdmaster.c jdpostct.c jdsample.c \ jerror.c jutils.c jfdctllm.c jidctllm.c jidctred.c jquant1.c \ jquant2.c jmemmgr.c jmemansi.c jmemname.c jmemnobs.c jmemdos.c # source files: cjpeg/djpeg applications APPSOURCES= cjpeg.c djpeg.c rdppm.c wrppm.c rdgif.c wrgif.c rdtarga.c \ wrtarga.c SOURCES= $(LIBSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ jpeglib.h jversion.h cdjpeg.h cderror.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 example.c libjpeg.doc \ structure.doc coderules.doc filelist.doc change.log MAKEFILES= configure makefile.auto makefile.ansi makefile.unix \ makefile.manx makefile.sas makcjpeg.st makdjpeg.st makljpeg.st \ makefile.bcc makefile.mc6 makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.auto jconfig.manx jconfig.sas jconfig.st jconfig.bcc \ jconfig.mc6 jconfig.vms OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.obj jutils.obj jerror.obj jmemmgr.obj $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapi.obj jcparam.obj jdatadst.obj jcmaster.obj jcmarker.obj \ jcmainct.obj jcprepct.obj jccoefct.obj jccolor.obj jcsample.obj \ jchuff.obj jcdctmgr.obj jfdctllm.obj # decompression library object files DLIBOBJECTS= jdapi.obj jdatasrc.obj jdmaster.obj jdmarker.obj jdmainct.obj \ jdcoefct.obj jdpostct.obj jddctmgr.obj jidctllm.obj jidctred.obj \ jdhuff.obj jdsample.obj jdcolor.obj jquant1.obj jquant2.obj # These objectfiles are included in libjpeg.olb LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for cjpeg and djpeg applications (excluding library files) COBJECTS= cjpeg.obj rdppm.obj rdgif.obj rdtarga.obj DOBJECTS= djpeg.obj wrppm.obj wrgif.obj wrtarga.obj # objectfile lists with commas --- what a crock COBJLIST= cjpeg.obj,rdppm.obj,rdgif.obj,rdtarga.obj DOBJLIST= djpeg.obj,wrppm.obj,wrgif.obj,wrtarga.obj LIBOBJLIST= jcapi.obj,jcparam.obj,jdatadst.obj,jcmaster.obj,jcmarker.obj,\ jcmainct.obj,jcprepct.obj,jccoefct.obj,jccolor.obj,jcsample.obj,\ jchuff.obj,jcdctmgr.obj,jfdctllm.obj,jdapi.obj,jdatasrc.obj,\ jdmaster.obj,jdmarker.obj,jdmainct.obj,jdcoefct.obj,jdpostct.obj,\ jddctmgr.obj,jidctllm.obj,jidctred.obj,jdhuff.obj,jdsample.obj,\ jdcolor.obj,jquant1.obj,jquant2.obj,jcomapi.obj,jutils.obj,\ jerror.obj,jmemmgr.obj,$(SYSDEPMEM) .first @ Define Sys Sys$Library ALL : libjpeg.olb cjpeg.exe djpeg.exe @ Continue libjpeg.olb : $(LIBOBJECTS) Library /Create libjpeg.olb $(LIBOBJLIST) cjpeg.exe : $(COBJECTS) libjpeg.olb $(LINK) $(LFLAGS) /Executable = cjpeg.exe $(COBJLIST),libjpeg.olb/Library,$(OPT)/Option djpeg.exe : $(DOBJECTS) libjpeg.olb $(LINK) $(LFLAGS) /Executable = djpeg.exe $(DOBJLIST),libjpeg.olb/Library,$(OPT)/Option clean : @- Set Protection = Owner:RWED *.*;-1 @- Set Protection = Owner:RWED *.OBJ - Purge /NoLog /NoConfirm *.* - Delete /NoLog /NoConfirm *.OBJ; test : cjpeg.exe djpeg.exe mcr sys$disk:[]djpeg -outfile testout.ppm testorig.jpg mcr sys$disk:[]djpeg -gif -outfile testout.gif testorig.jpg mcr sys$disk:[]cjpeg -outfile testout.jpg testimg.ppm - Backup /Compare/Log testimg.ppm testout.ppm - Backup /Compare/Log testimg.gif testout.gif - Backup /Compare/Log testimg.jpg testout.jpg jcapi.obj : jcapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccoefct.obj : jccoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jccolor.obj : jccolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcdctmgr.obj : jcdctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jchuff.obj : jchuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmainct.obj : jcmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmarker.obj : jcmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcmaster.obj : jcmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcomapi.obj : jcomapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcparam.obj : jcparam.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcprepct.obj : jcprepct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jcsample.obj : jcsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdapi.obj : jdapi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdatasrc.obj : jdatasrc.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdatadst.obj : jdatadst.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h jdcoefct.obj : jdcoefct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdcolor.obj : jdcolor.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jddctmgr.obj : jddctmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jdhuff.obj : jdhuff.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmainct.obj : jdmainct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmarker.obj : jdmarker.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdmaster.obj : jdmaster.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdpostct.obj : jdpostct.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdsample.obj : jdsample.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jerror.obj : jerror.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jversion.h jerror.h jutils.obj : jutils.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jfdctllm.obj : jfdctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctllm.obj : jidctllm.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jidctred.obj : jidctred.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jdct.h jquant1.obj : jquant1.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jquant2.obj : jquant2.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemmgr.obj : jmemmgr.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemansi.obj : jmemansi.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemname.obj : jmemname.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemnobs.obj : jmemnobs.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h jmemdos.obj : jmemdos.c jinclude.h jconfig.h jpeglib.h jmorecfg.h jpegint.h jerror.h jmemsys.h cjpeg.obj : cjpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h djpeg.obj : djpeg.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h jversion.h rdppm.obj : rdppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrppm.obj : wrppm.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdgif.obj : rdgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrgif.obj : wrgif.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h rdtarga.obj : rdtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h wrtarga.obj : wrtarga.c cdjpeg.h jinclude.h jconfig.h jpeglib.h jmorecfg.h jerror.h cderror.h \ No newline at end of file diff --git a/Independent JPEG Group/makefile.sas b/Independent JPEG Group/makefile.sas new file mode 100644 index 0000000..4994afc --- /dev/null +++ b/Independent JPEG Group/makefile.sas @@ -0,0 +1 @@ +# Makefile for Independent JPEG Group's software # This makefile is for Amiga systems using SAS C 6.0 and up. # Thanks to Ed Hanway, Mark Rinfret, and Jim Zepeda. # Read installation instructions before saying "make" !! # The name of your C compiler: CC= sc # You may need to adjust these cc options: # Uncomment the following lines for generic 680x0 version ARCHFLAGS= cpu=any SUFFIX= # Uncomment the following lines for 68030-only version #ARCHFLAGS= cpu=68030 #SUFFIX=.030 CFLAGS= nostackcheck data=near parms=register optimize $(ARCHFLAGS) \ ignore=104 ignore=304 ignore=306 # ignore=104 disables warnings for mismatched const qualifiers # ignore=304 disables warnings for variables being optimized out # ignore=306 disables warnings for the inlining of functions # Generally, we recommend defining any configuration symbols in jconfig.h, # NOT via define switches here. # Link-time cc options: LDFLAGS= SC SD ND BATCH # To link any special libraries, add the necessary commands here. LDLIBS= LIB:scm.lib LIB:sc.lib # Put here the object file name for the correct system-dependent memory # manager file. For Amiga we recommend jmemname.o. SYSDEPMEM= jmemname.o # miscellaneous OS-dependent stuff # linker LN= slink # file deletion command RM= delete quiet # library (.lib) file creation command AR= oml # End of configurable options. # source files: JPEG library proper LIBSOURCES= jcapi.c jccoefct.c jccolor.c jcdctmgr.c jchuff.c jcmainct.c \ jcmarker.c jcmaster.c jcomapi.c jcparam.c jcprepct.c jcsample.c \ jdapi.c jdatasrc.c jdatadst.c jdcoefct.c jdcolor.c jddctmgr.c \ jdhuff.c jdmainct.c jdmarker.c jdmaster.c jdpostct.c jdsample.c \ jerror.c jutils.c jfdctllm.c jidctllm.c jidctred.c jquant1.c \ jquant2.c jmemmgr.c jmemansi.c jmemname.c jmemnobs.c jmemdos.c # source files: cjpeg/djpeg applications APPSOURCES= cjpeg.c djpeg.c rdppm.c wrppm.c rdgif.c wrgif.c rdtarga.c \ wrtarga.c SOURCES= $(LIBSOURCES) $(APPSOURCES) # files included by source files INCLUDES= jdct.h jerror.h jinclude.h jmemsys.h jmorecfg.h jpegint.h \ jpeglib.h jversion.h cdjpeg.h cderror.h # documentation, test, and support files DOCS= README install.doc usage.doc cjpeg.1 djpeg.1 example.c libjpeg.doc \ structure.doc coderules.doc filelist.doc change.log MAKEFILES= configure makefile.auto makefile.ansi makefile.unix \ makefile.manx makefile.sas makcjpeg.st makdjpeg.st makljpeg.st \ makefile.bcc makefile.mc6 makefile.mms makefile.vms makvms.opt CONFIGFILES= jconfig.auto jconfig.manx jconfig.sas jconfig.st jconfig.bcc \ jconfig.mc6 jconfig.vms OTHERFILES= jconfig.doc ckconfig.c ansi2knr.c ansi2knr.1 jmemdosa.asm TESTFILES= testorig.jpg testimg.ppm testimg.gif testimg.jpg DISTFILES= $(DOCS) $(MAKEFILES) $(CONFIGFILES) $(SOURCES) $(INCLUDES) \ $(OTHERFILES) $(TESTFILES) # library object files common to compression and decompression COMOBJECTS= jcomapi.o jutils.o jerror.o jmemmgr.o $(SYSDEPMEM) # compression library object files CLIBOBJECTS= jcapi.o jcparam.o jdatadst.o jcmaster.o jcmarker.o jcmainct.o \ jcprepct.o jccoefct.o jccolor.o jcsample.o jchuff.o jcdctmgr.o \ jfdctllm.o # decompression library object files DLIBOBJECTS= jdapi.o jdatasrc.o jdmaster.o jdmarker.o jdmainct.o jdcoefct.o \ jdpostct.o jddctmgr.o jidctllm.o jidctred.o jdhuff.o jdsample.o \ jdcolor.o jquant1.o jquant2.o # These objectfiles are included in libjpeg.lib LIBOBJECTS= $(CLIBOBJECTS) $(DLIBOBJECTS) $(COMOBJECTS) # object files for cjpeg and djpeg applications (excluding library files) COBJECTS= cjpeg.o rdppm.o rdgif.o rdtarga.o DOBJECTS= djpeg.o wrppm.o wrgif.o wrtarga.o all: libjpeg.lib cjpeg$(SUFFIX) djpeg$(SUFFIX) libjpeg.lib: $(LIBOBJECTS) -$(RM) libjpeg.lib $(AR) libjpeg.lib r $(LIBOBJECTS) cjpeg$(SUFFIX): $(COBJECTS) libjpeg.lib $(LN) table of prefix symbols */ UINT8 FAR *symbol_tail; /* => table of suffix bytes */ UINT8 FAR *symbol_stack; /* => stack for symbol expansions */ UINT8 FAR *sp; /* stack pointer */ /* State for interlaced image processing */ boolean is_interlaced; /* TRUE if have interlaced image */ jvirt_sarray_ptr interlaced_image; /* full image in interlaced order */ JDIMENSION cur_row_number; /* need to know actual row number */ JDIMENSION pass2_offset; /* # of pixel rows in pass 1 */ JDIMENSION pass3_offset; /* # of pixel rows in passes 1&2 */ JDIMENSION pass4_offset; /* # of pixel rows in passes 1,2,3 */ } gif_source_struct; typedef gif_source_struct * gif_source_ptr; /* Forward declarations */ METHODDEF JDIMENSION get_pixel_rows JPP((j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); METHODDEF JDIMENSION load_interlaced_image JPP((j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); METHODDEF JDIMENSION get_interlaced_row JPP((j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); LOCAL int ReadByte (gif_source_ptr sinfo) /* Read next byte from GIF file */ { register FILE * infile = sinfo->pub.input_file; int c; if ((c = getc(infile)) == EOF) ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); return c; } LOCAL int GetDataBlock (gif_source_ptr sinfo, char *buf) /* Read a GIF data block, which has a leading count byte */ /* A zero-length block marks the end of a data block sequence */ { int count; count = ReadByte(sinfo); if (count > 0) { if (! ReadOK(sinfo->pub.input_file, buf, count)) ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); } return count; } LOCAL void SkipDataBlocks (gif_source_ptr sinfo) /* Skip a series of data blocks, until a block terminator is found */ { char buf[256]; while (GetDataBlock(sinfo, buf) > 0) /* skip */; } LOCAL void ReInitLZW (gif_source_ptr sinfo) /* (Re)initialize LZW state; shared code for startup and Clear processing */ { sinfo->code_size = sinfo->input_code_size + 1; sinfo->limit_code = sinfo->clear_code << 1; /* 2^code_size */ sinfo->max_code = sinfo->clear_code + 2; /* first unused code value */ sinfo->sp = sinfo->symbol_stack; /* init stack to empty */ } LOCAL void InitLZWCode (gif_source_ptr sinfo) /* Initialize for a series of LZWReadByte (and hence GetCode) calls */ { /* GetCode initialization */ sinfo->last_byte = 2; /* make safe to "recopy last two bytes" */ sinfo->last_bit = 0; /* nothing in the buffer */ sinfo->cur_bit = 0; /* force buffer load on first call */ sinfo->out_of_blocks = FALSE; /* LZWReadByte initialization: */ /* compute special code values (note that these do not change later) */ sinfo->clear_code = 1 << sinfo->input_code_size; sinfo->end_code = sinfo->clear_code + 1; sinfo->first_time = TRUE; ReInitLZW(sinfo); } LOCAL int GetCode (gif_source_ptr sinfo) /* Fetch the next code_size bits from the GIF data */ /* We assume code_size is less than 16 */ { register INT32 accum; int offs, ret, count; if ( (sinfo->cur_bit + sinfo->code_size) > sinfo->last_bit) { /* Time to reload the buffer */ if (sinfo->out_of_blocks) { WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); return sinfo->end_code; /* fake something useful */ } /* preserve last two bytes of what we have -- assume code_size <= 16 */ sinfo->code_buf[0] = sinfo->code_buf[sinfo->last_byte-2]; sinfo->code_buf[1] = sinfo->code_buf[sinfo->last_byte-1]; /* Load more bytes; set flag if we reach the terminator block */ if ((count = GetDataBlock(sinfo, &sinfo->code_buf[2])) == 0) { sinfo->out_of_blocks = TRUE; WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); return sinfo->end_code; /* fake something useful */ } /* Reset counters */ sinfo->cur_bit = (sinfo->cur_bit - sinfo->last_bit) + 16; sinfo->last_byte = 2 + count; sinfo->last_bit = sinfo->last_byte * 8; } /* Form up next 24 bits in accum */ offs = sinfo->cur_bit >> 3; /* byte containing cur_bit */ #ifdef CHAR_IS_UNSIGNED accum = sinfo->code_buf[offs+2]; accum <<= 8; accum |= sinfo->code_buf[offs+1]; accum <<= 8; accum |= sinfo->code_buf[offs]; #else accum = sinfo->code_buf[offs+2] & 0xFF; accum <<= 8; accum |= sinfo->code_buf[offs+1] & 0xFF; accum <<= 8; accum |= sinfo->code_buf[offs] & 0xFF; #endif /* Right-align cur_bit in accum, then mask off desired number of bits */ accum >>= (sinfo->cur_bit & 7); ret = ((int) accum) & ((1 << sinfo->code_size) - 1); sinfo->cur_bit += sinfo->code_size; return ret; } LOCAL int LZWReadByte (gif_source_ptr sinfo) /* Read an LZW-compressed byte */ { register int code; /* current working code */ int incode; /* saves actual input code */ /* First time, just eat the expected Clear code(s) and return next code, */ /* which is expected to be a raw byte. */ if (sinfo->first_time) { sinfo->first_time = FALSE; code = sinfo->clear_code; /* enables sharing code with Clear case */ } else { /* If any codes are stacked from a previously read symbol, return them */ if (sinfo->sp > sinfo->symbol_stack) return (int) *(-- sinfo->sp); /* Time to read a new symbol */ code = GetCode(sinfo); } if (code == sinfo->clear_code) { /* Reinit state, swallow any extra Clear codes, and */ /* return next code, which is expected to be a raw byte. */ ReInitLZW(sinfo); do { code = GetCode(sinfo); } while (code == sinfo->clear_code); if (code > sinfo->clear_code) { /* make sure it is a raw byte */ WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); code = 0; /* use something valid */ } /* make firstcode, oldcode valid! */ sinfo->firstcode = sinfo->oldcode = code; return code; } if (code == sinfo->end_code) { /* Skip the rest of the image, unless GetCode already read terminator */ if (! sinfo->out_of_blocks) { SkipDataBlocks(sinfo); sinfo->out_of_blocks = TRUE; } /* Complain that there's not enough data */ WARNMS(sinfo->cinfo, JWRN_GIF_ENDCODE); /* Pad data with 0's */ return 0; /* fake something usable */ } /* Got normal raw byte or LZW symbol */ incode = code; /* save for a moment */ if (code >= sinfo->max_code) { /* special case for not-yet-defined symbol */ /* code == max_code is OK; anything bigger is bad data */ if (code > sinfo->max_code) { WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); incode = 0; /* prevent creation of loops in symbol table */ } /* this symbol will be defined as oldcode/firstcode */ *(sinfo->sp++) = (UINT8) sinfo->firstcode; code = sinfo->oldcode; } /* If it's a symbol, expand it into the stack */ while (code >= sinfo->clear_code) { *(sinfo->sp++) = sinfo->symbol_tail[code]; /* tail is a byte value */ code = sinfo->symbol_head[code]; /* head is another LZW symbol */ } /* At this point code just represents a raw byte */ sinfo->firstcode = code; /* save for possible future use */ /* If there's room in table, */ if ((code = sinfo->max_code) < LZW_TABLE_SIZE) { /* Define a new symbol = prev sym + head of this sym's expansion */ sinfo->symbol_head[code] = sinfo->oldcode; sinfo->symbol_tail[code] = (UINT8) sinfo->firstcode; sinfo->max_code++; /* Is it time to increase code_size? */ if ((sinfo->max_code >= sinfo->limit_code) && (sinfo->code_size < MAX_LZW_BITS)) { sinfo->code_size++; sinfo->limit_code <<= 1; /* keep equal to 2^code_size */ } } sinfo->oldcode = incode; /* save last input symbol for future use */ return sinfo->firstcode; /* return first byte of symbol's expansion */ } LOCAL void ReadColorMap (gif_source_ptr sinfo, int cmaplen, JSAMPARRAY cmap) /* Read a GIF colormap */ { int i; for (i = 0; i < cmaplen; i++) { cmap[CM_RED][i] = (JSAMPLE) ReadByte(sinfo); cmap[CM_GREEN][i] = (JSAMPLE) ReadByte(sinfo); cmap[CM_BLUE][i] = (JSAMPLE) ReadByte(sinfo); } } LOCAL void DoExtension (gif_source_ptr sinfo) /* Process an extension block */ /* Currently we ignore 'em all */ { int extlabel; /* Read extension label byte */ extlabel = ReadByte(sinfo); TRACEMS1(sinfo->cinfo, 1, JTRC_GIF_EXTENSION, extlabel); /* Skip the data block(s) associated with the extension */ SkipDataBlocks(sinfo); } /* * Read the file header; return image size and component count. */ METHODDEF void start_input (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { gif_source_ptr source = (gif_source_ptr) sinfo; char hdrbuf[10]; /* workspace for reading control blocks */ unsigned int width, height; /* image dimensions */ int colormaplen, aspectRatio; int c; /* Allocate space to store the colormap */ source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) MAXCOLORMAPSIZE, (JDIMENSION) NUMCOLORS); /* Read and verify GIF Header */ if (! ReadOK(source->pub.input_file, hdrbuf, 6)) ERREXIT(cinfo, JERR_GIF_NOT); if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F') ERREXIT(cinfo, JERR_GIF_NOT); /* Check for expected version numbers. * If unknown version, give warning and try to process anyway; * this is per recommendation in GIF89a standard. */ if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') && (hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a')) TRACEMS3(cinfo, 1, JTRC_GIF_BADVERSION, hdrbuf[3], hdrbuf[4], hdrbuf[5]); /* Read and decipher Logical Screen Descriptor */ if (! ReadOK(source->pub.input_file, hdrbuf, 7)) ERREXIT(cinfo, JERR_INPUT_EOF); width = LM_to_uint(hdrbuf[0],hdrbuf[1]); height = LM_to_uint(hdrbuf[2],hdrbuf[3]); colormaplen = 2 << (hdrbuf[4] & 0x07); /* we ignore the color resolution, sort flag, and background color index */ aspectRatio = hdrbuf[6] & 0xFF; if (aspectRatio != 0 && aspectRatio != 49) TRACEMS(cinfo, 1, JTRC_GIF_NONSQUARE); /* Read global colormap if header indicates it is present */ if (BitSet(hdrbuf[4], COLORMAPFLAG)) ReadColorMap(source, colormaplen, source->colormap); /* Scan until we reach start of desired image. * We don't currently support skipping images, but could add it easily. */ for (;;) { c = ReadByte(source); if (c == ';') /* GIF terminator?? */ ERREXIT(cinfo, JERR_GIF_IMAGENOTFOUND); if (c == '!') { /* Extension */ DoExtension(source); continue; } if (c != ',') { /* Not an image separator? */ WARNMS1(cinfo, JWRN_GIF_CHAR, c); continue; } /* Read and decipher Local Image Descriptor */ if (! ReadOK(source->pub.input_file, hdrbuf, 9)) ERREXIT(cinfo, JERR_INPUT_EOF); /* we ignore top/left position info, also sort flag */ width = LM_to_uint(hdrbuf[4],hdrbuf[5]); height = LM_to_uint(hdrbuf[6],hdrbuf[7]); source->is_interlaced = BitSet(hdrbuf[8], INTERLACE); /* Read local colormap if header indicates it is present */ /* Note: if we wanted to support skipping images, */ /* we'd need to skip rather than read colormap for ignored images */ if (BitSet(hdrbuf[8], COLORMAPFLAG)) { colormaplen = 2 << (hdrbuf[8] & 0x07); ReadColorMap(source, colormaplen, source->colormap); } source->input_code_size = ReadByte(source); /* get min-code-size byte */ if (source->input_code_size < 2 || source->input_code_size >= MAX_LZW_BITS) ERREXIT1(cinfo, JERR_GIF_CODESIZE, source->input_code_size); /* Reached desired image, so break out of loop */ /* If we wanted to skip this image, */ /* we'd call SkipDataBlocks and then continue the loop */ break; } /* Prepare to read selected image: first initialize LZW decompressor */ source->symbol_head = (UINT16 FAR *) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT16)); source->symbol_tail = (UINT8 FAR *) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT8)); source->symbol_stack = (UINT8 FAR *) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, LZW_TABLE_SIZE * SIZEOF(UINT8)); InitLZWCode(source); /* * If image is interlaced, we read it into a full-size sample array, * decompressing as we go; then get_interlaced_row selects rows from the * sample array in the proper order. */ if (source->is_interlaced) { /* We request the virtual array now, but can't access it until virtual * arrays have been allocated. Hence, the actual work of reading the * image is postponed until the first call to get_pixel_rows. */ source->interlaced_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) width, (JDIMENSION) height, (JDIMENSION) 1); if (cinfo->progress != NULL) cinfo->progress->total_passes++; /* count file input as separate pass */ source->pub.get_pixel_rows = load_interlaced_image; } else { source->pub.get_pixel_rows = get_pixel_rows; } /* Create compressor input buffer. */ source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) width * NUMCOLORS, (JDIMENSION) 1); source->pub.buffer_height = 1; /* Return info about the image. */ cinfo->input_components = NUMCOLORS; cinfo->in_color_space = JCS_RGB; cinfo->image_width = width; cinfo->image_height = height; TRACEMS3(cinfo, 1, JTRC_GIF, width, height, colormaplen); } /* * Read one row of pixels. * This version is used for noninterlaced GIF images: * we read directly from the GIF file. */ METHODDEF JDIMENSION get_pixel_rows (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { gif_source_ptr source = (gif_source_ptr) sinfo; register int c; register JSAMPROW ptr; register JDIMENSION col; register JSAMPARRAY colormap = source->colormap; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { c = LZWReadByte(source); *ptr++ = colormap[CM_RED][c]; *ptr++ = colormap[CM_GREEN][c]; *ptr++ = colormap[CM_BLUE][c]; } return 1; } /* * Read one row of pixels. * This version is used for the first call on get_pixel_rows when * reading an interlaced GIF file: we read the whole image into memory. */ METHODDEF JDIMENSION load_interlaced_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { gif_source_ptr source = (gif_source_ptr) sinfo; JSAMPARRAY image_ptr; register JSAMPROW sptr; register JDIMENSION col; JDIMENSION row; /* Read the interlaced image into the virtual array we've created. */ for (row = 0; row < cinfo->image_height; row++) { if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) row; cinfo->progress->pass_limit = (long) cinfo->image_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } image_ptr = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, source->interlaced_image, row, TRUE); sptr = image_ptr[0]; for (col = cinfo->image_width; col > 0; col--) { *sptr++ = (JSAMPLE) LZWReadByte(source); } } if (cinfo->progress != NULL) cinfo->progress->completed_passes++; /* Replace method pointer so subsequent calls don't come here. */ source->pub.get_pixel_rows = get_interlaced_row; /* Initialize for get_interlaced_row, and perform first call on it. */ source->cur_row_number = 0; source->pass2_offset = (cinfo->image_height + 7) / 8; source->pass3_offset = source->pass2_offset + (cinfo->image_height + 3) / 8; source->pass4_offset = source->pass3_offset + (cinfo->image_height + 1) / 4; return get_interlaced_row(cinfo, sinfo); } /* * Read one row of pixels. * This version is used for interlaced GIF images: * we read from the virtual array. */ METHODDEF JDIMENSION get_interlaced_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { gif_source_ptr source = (gif_source_ptr) sinfo; JSAMPARRAY image_ptr; register int c; register JSAMPROW sptr, ptr; register JDIMENSION col; register JSAMPARRAY colormap = source->colormap; JDIMENSION irow; /* Figure out which row of interlaced image is needed, and access it. */ switch ((int) (source->cur_row_number & 7)) { case 0: /* first-pass row */ irow = source->cur_row_number >> 3; break; case 4: /* second-pass row */ irow = (source->cur_row_number >> 3) + source->pass2_offset; break; case 2: /* third-pass row */ case 6: irow = (source->cur_row_number >> 2) + source->pass3_offset; break; default: /* fourth-pass row */ irow = (source->cur_row_number >> 1) + source->pass4_offset; break; } image_ptr = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, source->interlaced_image, irow, FALSE); /* Scan the row, expand colormap, and output */ sptr = image_ptr[0]; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { c = GETJSAMPLE(*sptr++); *ptr++ = colormap[CM_RED][c]; *ptr++ = colormap[CM_GREEN][c]; *ptr++ = colormap[CM_BLUE][c]; } source->cur_row_number++; /* for next time */ return 1; } /* * Finish up at the end of the file. */ METHODDEF void finish_input (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { /* no work */ } /* * The module selection routine for GIF format input. */ GLOBAL cjpeg_source_ptr jinit_read_gif (j_compress_ptr cinfo) { gif_source_ptr source; /* Create module interface object */ source = (gif_source_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(gif_source_struct)); source->cinfo = cinfo; /* make back link for subroutines */ /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input; source->pub.finish_input = finish_input; return (cjpeg_source_ptr) source; } #endif /* GIF_SUPPORTED */ \ No newline at end of file diff --git a/Independent JPEG Group/rdppm.c b/Independent JPEG Group/rdppm.c new file mode 100644 index 0000000..a4bf447 --- /dev/null +++ b/Independent JPEG Group/rdppm.c @@ -0,0 +1 @@ +/* * rdppm.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to read input images in PPM/PGM format. * The PBMPLUS library is NOT required to compile this software * (but it is highly useful as a set of PPM image manipulation programs). * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume input from * an ordinary stdio stream. They further assume that reading begins * at the start of the file; start_input may need work if the * user interface has already read some data (e.g., to determine that * the file is indeed PPM format). */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #ifdef PPM_SUPPORTED /* Portions of this code are based on the PBMPLUS library, which is: ** ** Copyright (C) 1988 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ /* Macros to deal with unsigned chars as efficiently as compiler allows */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char U_CHAR; #define UCH(x) ((int) (x)) #else /* !HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char U_CHAR; #define UCH(x) ((int) (x)) #else typedef char U_CHAR; #define UCH(x) ((int) (x) & 0xFF) #endif #endif /* HAVE_UNSIGNED_CHAR */ #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) /* * On most systems, reading individual bytes with getc() is drastically less * efficient than buffering a row at a time with fread(). On PCs, we must * allocate the buffer in near data space, because we are assuming small-data * memory model, wherein fread() can't reach far memory. If you need to * process very wide images on a PC, you might have to compile in large-memory * model, or else replace fread() with a getc() loop --- which will be much * slower. */ /* Private version of data source object */ typedef struct { struct cjpeg_source_struct pub; /* public fields */ U_CHAR *iobuffer; /* non-FAR pointer to I/O buffer */ JSAMPROW pixrow; /* FAR pointer to same */ JDIMENSION buffer_width; /* width of one row */ JSAMPLE *rescale; /* => maxval-remapping array, or NULL */ } ppm_source_struct; typedef ppm_source_struct * ppm_source_ptr; LOCAL int pbm_getc (FILE * infile) /* Read next char, skipping over any comments */ /* A comment/newline sequence is returned as a newline */ { register int ch; ch = getc(infile); if (ch == '#') { do { ch = getc(infile); } while (ch != '\n' && ch != EOF); } return ch; } LOCAL unsigned int read_pbm_integer (j_compress_ptr cinfo, FILE * infile) /* Read an unsigned decimal integer from the PPM file */ /* Swallows one trailing character after the integer */ /* Note that on a 16-bit-int machine, only values up to 64k can be read. */ /* This should not be a problem in practice. */ { register int ch; register unsigned int val; /* Skip any leading whitespace */ do { ch = pbm_getc(infile); if (ch == EOF) ERREXIT(cinfo, JERR_INPUT_EOF); } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); if (ch < '0' || ch > '9') ERREXIT(cinfo, JERR_PPM_NONNUMERIC); val = ch - '0'; while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') { val *= 10; val += ch - '0'; } return val; } /* * Read one row of pixels. * * We provide several different versions depending on input file format. * In all cases, input is scaled to the size of JSAMPLE. * * Note that a really fast path is provided for reading raw files with * maxval = MAXJSAMPLE, which is the normal case (at least for 8-bit JSAMPLEs). */ METHODDEF JDIMENSION get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading text-format PGM files with any maxval */ { ppm_source_ptr source = (ppm_source_ptr) sinfo; FILE * infile = source->pub.input_file; register JSAMPROW ptr; register JSAMPLE *rescale = source->rescale; JDIMENSION col; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; } return 1; } METHODDEF JDIMENSION get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading text-format PPM files with any maxval */ { ppm_source_ptr source = (ppm_source_ptr) sinfo; FILE * infile = source->pub.input_file; register JSAMPROW ptr; register JSAMPLE *rescale = source->rescale; JDIMENSION col; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; *ptr++ = rescale[read_pbm_integer(cinfo, infile)]; } return 1; } METHODDEF JDIMENSION get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading raw-format PGM files with any maxval */ { ppm_source_ptr source = (ppm_source_ptr) sinfo; register JSAMPROW ptr; register U_CHAR * bufferptr; register JSAMPLE *rescale = source->rescale; JDIMENSION col; if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) ERREXIT(cinfo, JERR_INPUT_EOF); ptr = source->pub.buffer[0]; bufferptr = source->iobuffer; for (col = cinfo->image_width; col > 0; col--) { *ptr++ = rescale[UCH(*bufferptr++)]; } return 1; } METHODDEF JDIMENSION get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading raw-format PPM files with any maxval */ { ppm_source_ptr source = (ppm_source_ptr) sinfo; register JSAMPROW ptr; register U_CHAR * bufferptr; register JSAMPLE *rescale = source->rescale; JDIMENSION col; if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) ERREXIT(cinfo, JERR_INPUT_EOF); ptr = source->pub.buffer[0]; bufferptr = source->iobuffer; for (col = cinfo->image_width; col > 0; col--) { *ptr++ = rescale[UCH(*bufferptr++)]; *ptr++ = rescale[UCH(*bufferptr++)]; *ptr++ = rescale[UCH(*bufferptr++)]; } return 1; } METHODDEF JDIMENSION get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading raw-format files with maxval = MAXJSAMPLE. */ /* In this case we just read right into the JSAMPLE buffer! */ /* Note that same code works for PPM and PGM files. */ { ppm_source_ptr source = (ppm_source_ptr) sinfo; if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width)) ERREXIT(cinfo, JERR_INPUT_EOF); return 1; } /* * Read the file header; return image size and component count. */ METHODDEF void start_input (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { ppm_source_ptr source = (ppm_source_ptr) sinfo; int c; unsigned int w, h, maxval; boolean can_use_raw; if (getc(source->pub.input_file) != 'P') ERREXIT(cinfo, JERR_PPM_NOT); c = getc(source->pub.input_file); /* save format discriminator for a sec */ /* while we fetch the remaining header info */ w = read_pbm_integer(cinfo, source->pub.input_file); h = read_pbm_integer(cinfo, source->pub.input_file); maxval = read_pbm_integer(cinfo, source->pub.input_file); if (w <= 0 || h <= 0 || maxval <= 0) /* error check */ ERREXIT(cinfo, JERR_PPM_NOT); cinfo->image_width = (JDIMENSION) w; cinfo->image_height = (JDIMENSION) h; /* Raw PPM/PGM matches JSAMPLE representation iff: */ can_use_raw = (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)); switch (c) { case '2': /* it's a text-format PGM file */ cinfo->input_components = 1; cinfo->in_color_space = JCS_GRAYSCALE; TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h); source->pub.get_pixel_rows = get_text_gray_row; can_use_raw = FALSE; /* force a rescale array to be made */ break; case '3': /* it's a text-format PPM file */ cinfo->input_components = 3; cinfo->in_color_space = JCS_RGB; TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h); source->pub.get_pixel_rows = get_text_rgb_row; can_use_raw = FALSE; /* force a rescale array to be made */ break; case '5': /* it's a raw-format PGM file */ cinfo->input_components = 1; cinfo->in_color_space = JCS_GRAYSCALE; TRACEMS2(cinfo, 1, JTRC_PGM, w, h); if (can_use_raw) source->pub.get_pixel_rows = get_raw_row; else source->pub.get_pixel_rows = get_scaled_gray_row; /* allocate space for I/O buffer: 1 byte/pixel */ source->iobuffer = (U_CHAR *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) (SIZEOF(U_CHAR) * (size_t) w)); break; case '6': /* it's a raw-format PPM file */ cinfo->input_components = 3; cinfo->in_color_space = JCS_RGB; TRACEMS2(cinfo, 1, JTRC_PPM, w, h); if (can_use_raw) source->pub.get_pixel_rows = get_raw_row; else source->pub.get_pixel_rows = get_scaled_rgb_row; /* allocate space for I/O buffer: 3 bytes/pixel */ source->iobuffer = (U_CHAR *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) (3 * SIZEOF(U_CHAR) * (size_t) w)); break; default: ERREXIT(cinfo, JERR_PPM_NOT); break; } /* Create compressor input buffer. */ source->buffer_width = (JDIMENSION) w * cinfo->input_components; if (can_use_raw) { /* For unscaled raw-input case, we can just map it onto the I/O buffer. */ /* Synthesize a JSAMPARRAY pointer structure */ /* Cast here implies near->far pointer conversion on PCs */ source->pixrow = (JSAMPROW) source->iobuffer; source->pub.buffer = & source->pixrow; source->pub.buffer_height = 1; } else { /* Need to translate anyway, so make a separate sample buffer. */ source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, source->buffer_width, (JDIMENSION) 1); source->pub.buffer_height = 1; } /* Compute the rescaling array if required (we use it for all but raw) */ if (can_use_raw) { source->rescale = NULL; /* no rescaling required */ } else { INT32 val, half_maxval; /* On 16-bit-int machines we have to be careful of maxval = 65535 */ source->rescale = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE))); half_maxval = maxval / 2; for (val = 0; val <= (INT32) maxval; val++) { /* The multiplication here must be done in 32 bits to avoid overflow */ source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval); } } } /* * Finish up at the end of the file. */ METHODDEF void finish_input (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { /* no work */ } /* * The module selection routine for PPM format input. */ GLOBAL cjpeg_source_ptr jinit_read_ppm (j_compress_ptr cinfo) { ppm_source_ptr source; /* Create module interface object */ source = (ppm_source_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(ppm_source_struct)); /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input; source->pub.finish_input = finish_input; return (cjpeg_source_ptr) source; } #endif /* PPM_SUPPORTED */ \ No newline at end of file diff --git a/Independent JPEG Group/rdtarga.c b/Independent JPEG Group/rdtarga.c new file mode 100644 index 0000000..0b58b1d --- /dev/null +++ b/Independent JPEG Group/rdtarga.c @@ -0,0 +1 @@ +/* * rdtarga.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to read input images in Targa format. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume input from * an ordinary stdio stream. They further assume that reading begins * at the start of the file; start_input may need work if the * user interface has already read some data (e.g., to determine that * the file is indeed Targa format). * * Based on code contributed by Lee Daniel Crocker. */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #ifdef TARGA_SUPPORTED /* Macros to deal with unsigned chars as efficiently as compiler allows */ #ifdef HAVE_UNSIGNED_CHAR typedef unsigned char U_CHAR; #define UCH(x) ((int) (x)) #else /* !HAVE_UNSIGNED_CHAR */ #ifdef CHAR_IS_UNSIGNED typedef char U_CHAR; #define UCH(x) ((int) (x)) #else typedef char U_CHAR; #define UCH(x) ((int) (x) & 0xFF) #endif #endif /* HAVE_UNSIGNED_CHAR */ #define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len))) /* Private version of data source object */ typedef struct _tga_source_struct * tga_source_ptr; typedef struct _tga_source_struct { struct cjpeg_source_struct pub; /* public fields */ j_compress_ptr cinfo; /* back link saves passing separate parm */ JSAMPARRAY colormap; /* Targa colormap (converted to my format) */ jvirt_sarray_ptr whole_image; /* Needed if funny input row order */ JDIMENSION current_row; /* Current logical row number to read */ /* Pointer to routine to extract next Targa pixel from input file */ JMETHOD(void, read_pixel, (tga_source_ptr sinfo)); /* Result of read_pixel is delivered here: */ U_CHAR tga_pixel[4]; int pixel_size; /* Bytes per Targa pixel (1 to 4) */ /* State info for reading RLE-coded pixels; both counts must be init to 0 */ int block_count; /* # of pixels remaining in RLE block */ int dup_pixel_count; /* # of times to duplicate previous pixel */ /* This saves the correct pixel-row-expansion method for preload_image */ JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)); } tga_source_struct; /* For expanding 5-bit pixel values to 8-bit with best rounding */ static const UINT8 c5to8bits[32] = { 0, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255 }; LOCAL int read_byte (tga_source_ptr sinfo) /* Read next byte from Targa file */ { register FILE *infile = sinfo->pub.input_file; register int c; if ((c = getc(infile)) == EOF) ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); return c; } LOCAL void read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize) /* Read the colormap from a Targa file */ { int i; /* Presently only handles 24-bit BGR format */ if (mapentrysize != 24) ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP); for (i = 0; i < cmaplen; i++) { sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo); sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo); sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo); } } /* * read_pixel methods: get a single pixel from Targa file into tga_pixel[] */ LOCAL void read_non_rle_pixel (tga_source_ptr sinfo) /* Read one Targa pixel from the input file; no RLE expansion */ { register FILE *infile = sinfo->pub.input_file; register int i; for (i = 0; i < sinfo->pixel_size; i++) { sinfo->tga_pixel[i] = (U_CHAR) getc(infile); } } LOCAL void read_rle_pixel (tga_source_ptr sinfo) /* Read one Targa pixel from the input file, expanding RLE data as needed */ { register FILE *infile = sinfo->pub.input_file; register int i; /* Duplicate previously read pixel? */ if (sinfo->dup_pixel_count > 0) { sinfo->dup_pixel_count--; return; } /* Time to read RLE block header? */ if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */ i = read_byte(sinfo); if (i & 0x80) { /* Start of duplicate-pixel block? */ sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */ sinfo->block_count = 0; /* then read new block header */ } else { sinfo->block_count = i & 0x7F; /* number of pixels after this one */ } } /* Read next pixel */ for (i = 0; i < sinfo->pixel_size; i++) { sinfo->tga_pixel[i] = (U_CHAR) getc(infile); } } /* * Read one row of pixels. * * We provide several different versions depending on input file format. */ METHODDEF JDIMENSION get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 8-bit grayscale pixels */ { tga_source_ptr source = (tga_source_ptr) sinfo; register JSAMPROW ptr; register JDIMENSION col; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]); } return 1; } METHODDEF JDIMENSION get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 8-bit colormap indexes */ { tga_source_ptr source = (tga_source_ptr) sinfo; register int t; register JSAMPROW ptr; register JDIMENSION col; register JSAMPARRAY colormap = source->colormap; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ t = UCH(source->tga_pixel[0]); *ptr++ = colormap[0][t]; *ptr++ = colormap[1][t]; *ptr++ = colormap[2][t]; } return 1; } METHODDEF JDIMENSION get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 16-bit pixels */ { tga_source_ptr source = (tga_source_ptr) sinfo; register int t; register JSAMPROW ptr; register JDIMENSION col; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ t = UCH(source->tga_pixel[0]); t += UCH(source->tga_pixel[1]) << 8; /* We expand 5 bit data to 8 bit sample width. * The format of the 16-bit (LSB first) input word is * xRRRRRGGGGGBBBBB */ ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F]; t >>= 5; ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F]; t >>= 5; ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F]; ptr += 3; } return 1; } METHODDEF JDIMENSION get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) /* This version is for reading 24-bit pixels */ { tga_source_ptr source = (tga_source_ptr) sinfo; register JSAMPROW ptr; register JDIMENSION col; ptr = source->pub.buffer[0]; for (col = cinfo->image_width; col > 0; col--) { (*source->read_pixel) (source); /* Load next pixel into tga_pixel */ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]); *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]); } return 1; } /* * Targa also defines a 32-bit pixel format with order B,G,R,A. * We presently ignore the attribute byte, so the code for reading * these pixels is identical to the 24-bit routine above. * This works because the actual pixel length is only known to read_pixel. */ #define get_32bit_row get_24bit_row /* * This method is for re-reading the input data in standard top-down * row order. The entire image has already been read into whole_image * with proper conversion of pixel format, but it's in a funny row order. */ METHODDEF JDIMENSION get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { tga_source_ptr source = (tga_source_ptr) sinfo; JDIMENSION source_row; /* Compute row of source that maps to current_row of normal order */ /* For now, assume image is bottom-up and not interlaced. */ /* NEEDS WORK to support interlaced images! */ source_row = cinfo->image_height - source->current_row - 1; /* Fetch that row from virtual array */ source->pub.buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, source->whole_image, source_row, FALSE); source->current_row++; return 1; } /* * This method loads the image into whole_image during the first call on * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call * get_memory_row on subsequent calls. */ METHODDEF JDIMENSION preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { tga_source_ptr source = (tga_source_ptr) sinfo; JDIMENSION row; /* Read the data into a virtual array in input-file row order. */ for (row = 0; row < cinfo->image_height; row++) { if (cinfo->progress != NULL) { cinfo->progress->pass_counter = (long) row; cinfo->progress->pass_limit = (long) cinfo->image_height; (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); } source->pub.buffer = (*cinfo->mem->access_virt_sarray) ((j_common_ptr) cinfo, source->whole_image, row, TRUE); (*source->get_pixel_rows) (cinfo, sinfo); } if (cinfo->progress != NULL) cinfo->progress->completed_passes++; /* Set up to read from the virtual array in unscrambled order */ source->pub.get_pixel_rows = get_memory_row; source->current_row = 0; /* And read the first row */ return get_memory_row(cinfo, sinfo); } /* * Read the file header; return image size and component count. */ METHODDEF void start_input (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { tga_source_ptr source = (tga_source_ptr) sinfo; U_CHAR targaheader[18]; int idlen, cmaptype, subtype, flags, interlace_type, components; unsigned int width, height, maplen; boolean is_bottom_up; #define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \ (((unsigned int) UCH(targaheader[offset+1])) << 8)) if (! ReadOK(source->pub.input_file, targaheader, 18)) ERREXIT(cinfo, JERR_INPUT_EOF); /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */ if (targaheader[16] == 15) targaheader[16] = 16; idlen = UCH(targaheader[0]); cmaptype = UCH(targaheader[1]); subtype = UCH(targaheader[2]); maplen = GET_2B(5); width = GET_2B(12); height = GET_2B(14); source->pixel_size = UCH(targaheader[16]) >> 3; flags = UCH(targaheader[17]); /* Image Descriptor byte */ is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */ interlace_type = flags >> 6; /* bits 6/7 are interlace code */ if (cmaptype > 1 || /* cmaptype must be 0 or 1 */ source->pixel_size < 1 || source->pixel_size > 4 || (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */ interlace_type != 0) /* currently don't allow interlaced image */ ERREXIT(cinfo, JERR_TGA_BADPARMS); if (subtype > 8) { /* It's an RLE-coded file */ source->read_pixel = read_rle_pixel; source->block_count = source->dup_pixel_count = 0; subtype -= 8; } else { /* Non-RLE file */ source->read_pixel = read_non_rle_pixel; } /* Now should have subtype 1, 2, or 3 */ components = 3; /* until proven different */ cinfo->in_color_space = JCS_RGB; switch (subtype) { case 1: /* Colormapped image */ if (source->pixel_size == 1 && cmaptype == 1) source->get_pixel_rows = get_8bit_row; else ERREXIT(cinfo, JERR_TGA_BADPARMS); TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height); break; case 2: /* RGB image */ switch (source->pixel_size) { case 2: source->get_pixel_rows = get_16bit_row; break; case 3: source->get_pixel_rows = get_24bit_row; break; case 4: source->get_pixel_rows = get_32bit_row; break; default: ERREXIT(cinfo, JERR_TGA_BADPARMS); break; } TRACEMS2(cinfo, 1, JTRC_TGA, width, height); break; case 3: /* Grayscale image */ components = 1; cinfo->in_color_space = JCS_GRAYSCALE; if (source->pixel_size == 1) source->get_pixel_rows = get_8bit_gray_row; else ERREXIT(cinfo, JERR_TGA_BADPARMS); TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height); break; default: ERREXIT(cinfo, JERR_TGA_BADPARMS); break; } if (is_bottom_up) { /* Create a virtual array to buffer the upside-down image. */ source->whole_image = (*cinfo->mem->request_virt_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1); if (cinfo->progress != NULL) cinfo->progress->total_passes++; /* count file input as separate pass */ /* source->pub.buffer will point to the virtual array. */ source->pub.buffer_height = 1; /* in case anyone looks at it */ source->pub.get_pixel_rows = preload_image; } else { /* Don't need a virtual array, but do need a one-row input buffer. */ source->whole_image = NULL; source->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) width * components, (JDIMENSION) 1); source->pub.buffer_height = 1; source->pub.get_pixel_rows = source->get_pixel_rows; } while (idlen--) /* Throw away ID field */ (void) read_byte(source); if (maplen > 0) { if (maplen > 256 || GET_2B(3) != 0) ERREXIT(cinfo, JERR_TGA_BADCMAP); /* Allocate space to store the colormap */ source->colormap = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3); /* and read it from the file */ read_colormap(source, (int) maplen, UCH(targaheader[7])); } else { if (cmaptype) /* but you promised a cmap! */ ERREXIT(cinfo, JERR_TGA_BADPARMS); source->colormap = NULL; } cinfo->input_components = components; cinfo->image_width = width; cinfo->image_height = height; } /* * Finish up at the end of the file. */ METHODDEF void finish_input (j_compress_ptr cinfo, cjpeg_source_ptr sinfo) { /* no work */ } /* * The module selection routine for Targa format input. */ GLOBAL cjpeg_source_ptr jinit_read_targa (j_compress_ptr cinfo) { tga_source_ptr source; /* Create module interface object */ source = (tga_source_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(tga_source_struct)); source->cinfo = cinfo; /* make back link for subroutines */ /* Fill in method ptrs, except get_pixel_rows which start_input sets */ source->pub.start_input = start_input; source->pub.finish_input = finish_input; return (cjpeg_source_ptr) source; } #endif /* TARGA_SUPPORTED */ \ No newline at end of file diff --git a/Independent JPEG Group/structure.doc b/Independent JPEG Group/structure.doc new file mode 100644 index 0000000..dd717ed --- /dev/null +++ b/Independent JPEG Group/structure.doc @@ -0,0 +1 @@ +IJG JPEG LIBRARY: SYSTEM ARCHITECTURE Copyright (C) 1991-1994, Thomas G. Lane. This file is part of the Independent JPEG Group's software. For conditions of distribution and use, see the accompanying README file. This file provides an overview of the architecture of the IJG JPEG software; that is, the functions of the various modules in the system and the interfaces between modules. For more precise details about any data structure or calling convention, see the include files and comments in the source code. We assume that the reader is already somewhat familiar with the JPEG standard. The README file includes references for learning about JPEG. The file libjpeg.doc describes the library from the viewpoint of an application programmer using the library; it's best to read that file before this one. Also, the file coderules.doc describes the coding style conventions we use. In this document, JPEG-specific terminology follows the JPEG standard: A "component" means a color channel, e.g., Red or Luminance. A "sample" is a single component value (i.e., one number in the image data). A "coefficient" is a frequency coefficient (a DCT transform output number). A "block" is an 8x8 group of samples or coefficients. An "MCU" (minimum coded unit) is an interleaved set of blocks of size determined by the sampling factors, or a single block in a noninterleaved scan. We do not use the terms "pixel" and "sample" interchangeably. When we say pixel, we mean an element of the full-size image; a sample is an element of the downsampled image. Thus the number of samples may vary across components while the number of pixels does not. (This terminology is not used rigorously throughout the code, but it is used in places where confusion would otherwise result.) *** System features *** The IJG distribution contains two parts: * A subroutine library for JPEG compression and decompression. * cjpeg/djpeg, two simple applications that use the library to transform JFIF JPEG files to and from several other image formats. cjpeg/djpeg are of no great intellectual complexity: they merely add a simple command-line user interface and I/O routines for several uncompressed image formats. This document concentrates on the library itself. We desire the library to be capable of supporting all JPEG baseline and extended sequential DCT processes. Progressive processes are also allowed for in the system architecture, although they are not likely to be implemented very soon. Hierarchical processes are not supported. The library does not support the lossless (spatial) JPEG process. Lossless JPEG shares little or no code with lossy JPEG, and would normally be used without the extensive pre- and post-processing provided by this library. We feel that lossless JPEG is better handled by a separate library. Within these limits, any set of compression parameters allowed by the JPEG spec should be readable for decompression. (We can be more restrictive about what formats we can generate.) Although the system design allows for all parameter values, some uncommon settings are not yet implemented and may never be; nonintegral sampling ratios are the prime example. Furthermore, we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a run-time option, because most machines can store 8-bit pixels much more compactly than 12-bit. For legal reasons, JPEG arithmetic coding is not currently supported, but extending the library to include it would be straightforward. By itself, the library handles only interchange JPEG datastreams --- in particular the widely used JFIF file format. The library can be used by surrounding code to process interchange or abbreviated JPEG datastreams that are embedded in more complex file formats. (For example, we anticipate that Sam Leffler's TIFF library will use this code to support the revised TIFF JPEG format.) The library includes a substantial amount of code that is not covered by the JPEG standard but is necessary for typical applications of JPEG. These functions preprocess the image before JPEG compression or postprocess it after decompression. They include colorspace conversion, downsampling/upsampling, and color quantization. This code can be omitted if not needed. A wide range of quality vs. speed tradeoffs are possible in JPEG processing, and even more so in decompression postprocessing. The decompression library provides multiple implementations that cover most of the useful tradeoffs, ranging from very-high-quality down to fast-preview operation. On the compression side we have generally not provided low-quality choices, since compression is normally less time-critical. It should be understood that the low-quality modes may not meet the JPEG standard's accuracy requirements; nonetheless, they are useful for viewers. *** Portability issues *** Portability is an essential requirement for the library. The key portability issues that show up at the level of system architecture are: 1. Memory usage. We want the code to be able to run on PC-class machines with limited memory. Images should therefore be processed sequentially (in strips), to avoid holding the whole image in memory at once. Where a full-image buffer is necessary, we should be able to use either virtual memory or temporary files. 2. Near/far pointer distinction. To run efficiently on 80x86 machines, the code should distinguish "small" objects (kept in near data space) from "large" ones (kept in far data space). This is an annoying restriction, but fortunately it does not impact code quality for less brain-damaged machines, and the source code clutter turns out to be minimal with sufficient use of pointer typedefs. 3. Data precision. We assume that "char" is at least 8 bits, "short" and "int" at least 16, "long" at least 32. The code will work fine with larger data sizes, although memory may be used inefficiently in some cases. However, the JPEG compressed datastream must ultimately appear on external storage as a sequence of 8-bit bytes if it is to conform to the standard. This may pose a problem on machines where char is wider than 8 bits. The library represents compressed data as an array of values of typedef JOCTET. If no data type exactly 8 bits wide is available, custom data source and data destination modules must be written to unpack and pack the chosen JOCTET datatype into 8-bit external representation. *** System overview *** The compressor and decompressor are each divided into two main sections: the JPEG compressor or decompressor proper, and the preprocessing or postprocessing functions. The interface between these two sections is the image data that the official JPEG spec regards as its input or output: this data is in the colorspace to be used for compression, and it is downsampled to the sampling factors to be used. The preprocessing and postprocessing steps are responsible for converting a normal image representation to or from this form. (Those few applications that want to deal with YCbCr downsampled data can skip the preprocessing or postprocessing step.) Looking more closely, the compressor library contains the following main elements: Preprocessing: * Color space conversion (e.g., RGB to YCbCr). This step may also provide gamma adjustment. * Edge expansion and downsampling. Optionally, this step can do simple smoothing --- this is often helpful for low-quality source data. JPEG proper: * MCU assembly, DCT, quantization. * Entropy coding (Huffman or arithmetic). In addition to these modules we need overall control, marker generation, and support code (memory management & error handling). There is also a module responsible for physically writing the output data --- typically this is just an interface to fwrite(), but some applications may need to do something else with the data. The decompressor library contains the following main elements: JPEG proper: * Entropy decoding (Huffman or arithmetic). * Dequantization, inverse DCT, MCU disassembly. Postprocessing: * Upsampling. Optionally, this step may be able to do more general rescaling of the image. * Color space conversion (e.g., YCbCr to RGB). This step may also provide gamma adjustment. * Optional color quantization (e.g., reduction to 256 colors). * Optional color precision reduction (e.g., 24-bit to 15-bit color). We also need overall control, marker parsing, and a data source module. The support code (memory management & error handling) can be shared with the compression half of the library. There may be several implementations of each of these elements, particularly in the decompressor, where a wide range of speed/quality tradeoffs is very useful. It must be understood that some of the best speedups involve merging adjacent steps in the pipeline. For example, upsampling, color space conversion, and color quantization might all be done at once when using a low-quality ordered-dither technique. The system architecture is designed to allow such merging where appropriate. Note: it is convenient to regard edge expansion (padding to block boundaries) as a preprocessing/postprocessing function, even though the JPEG spec includes it in compression/decompression. We do this because downsampling/upsampling can be simplified a little if they work on padded data: it's not necessary to have special cases at the right and bottom edges. Therefore the interface buffer is always an integral number of blocks wide and high, and we expect compression preprocessing to pad the source data properly. Padding will occur only to the next block (8-sample) boundary. In an interleaved-scan situation, additional dummy blocks may be used to fill out MCUs, but the MCU assembly and disassembly logic will create or discard these blocks internally. (This is advantageous for speed reasons, since we avoid DCTing the dummy blocks; and it also permits a small reduction in file size.) Applications that wish to deal directly with the downsampled data must provide similar buffering and padding for odd-sized images. *** Poor man's object-oriented programming *** It should be clear by now that we have a lot of quasi-independent processing steps, many of which have several possible behaviors. To avoid cluttering the code with lots of switch statements, we use a simple form of object-style programming to separate out the different possibilities. For example, two different color quantization algorithms could be implemented as two separate modules that present the same external interface; at runtime, the calling code will access the proper module indirectly through an "object". We can get the limited features we need while staying within portable C. The basic tool is a function pointer. An "object" is just a struct containing one or more function pointer fields, each of which corresponds to a method name in real object-oriented languages. During initialization we fill in the function pointers with references to whichever module we have determined we need to use in this run. Then invocation of the module is done by indirecting through a function pointer; on most machines this is no more expensive than a switch statement, which would be the only other way of making the required run-time choice. The really significant benefit, of course, is keeping the source code clean and well structured. We can also arrange to have private storage that varies between different implementations of the same kind of object. We do this by making all the module-specific object structs be separately allocated entities, which will be accessed via pointers in the master compression or decompression struct. The "public" fields or methods for a given kind of object are specified by a commonly known struct. But a module's initialization code can allocate a larger struct that contains the common struct as its first member, plus additional private fields. With appropriate pointer casting, the module's internal functions can access these private fields. (For a simple example, see jdatadst.c, which implements the external interface specified by struct jpeg_destination_mgr, but adds extra fields.) (Of course this would all be a lot easier if we were using C++, but we are not yet prepared to assume that everyone has a C++ compiler.) An important benefit of this scheme is that it is easy to provide multiple versions of any method, each tuned to a particular case. While a lot of precalculation might be done to select an optimal implementation of a method, the cost per invocation is constant. For example, the upsampling step might have a "generic" method, plus one or more "hardwired" methods for the most popular sampling factors; the hardwired methods would be faster because they'd use straight-line code instead of for-loops. The cost to determine which method to use is paid only once, at startup, and the selection criteria are hidden from the callers of the method. This plan differs a little bit from usual object-oriented structures, in that only one instance of each object class will exist during execution. The reason for having the class structure is that on different runs we may create different instances (choose to execute different modules). You can think of the term "method" as denoting the common interface presented by a particular set of interchangeable functions, and "object" as denoting a group of related methods, or the total shared interface behavior of a group of modules. *** Overall control structure *** We previously mentioned the need for overall control logic in the compression and decompression libraries. In the previous IJG implementation, overall control was mostly provided by "pipeline control" modules, which proved to be large, unwieldy, and hard to understand. In hopes of improving the situation, the control logic will be subdivided this time around. The control modules will consist of: 1. Master control for module selection and initialization. This has two responsibilities: 1A. Startup initialization at the beginning of image processing. The individual processing modules to be used in this run are selected and given initialization calls. 1B. Per-pass control. This determines how many passes will be performed and calls each active processing module to configure itself appropriately at the beginning of each pass. End-of-pass processing, where necessary, is also invoked from the master control module. Method selection is partially distributed, in that a particular processing module may contain several possible implementations of a particular method, which it will select among when given its initialization call. The master control code need only be concerned with decisions that affect more than one module. 2. Data buffering control. A separate control module will exist for each inter-processing-step data buffer. This module will be responsible for invoking the processing steps that write or read that data buffer. Each buffer controller sees the world as follows: input data => processing step A => buffer => processing step B => output data | | | ------------------ controller ------------------ The controller knows the dataflow requirements of steps A and B: how much data they want to accept in one chunk and how much they output in one chunk. Its function is to manage its buffer and call A and B at the proper times. A data buffer control module may itself be viewed as a processing step by a higher-level control module; thus the control modules form a binary tree with elementary processing steps at the leaves of the tree. The control modules will be objects. A considerable amount of flexibility can be had by replacing implementations of a control module. For example: * Merging of adjacent steps in the pipeline is done by replacing a control module and its pair of processing-step modules with a single processing- step module. (Hence the possible merges are determined by the tree of control modules.) * In some processing modes, a given interstep buffer need only be a "strip" buffer large enough to accommodate the desired data chunk sizes. In other modes, a full-image buffer is needed and several passes are required. The control module determines which kind of buffer is used and manipulates virtual array buffers as needed. One or both processing steps may be unaware of the multi-pass behavior. In theory, we might be able to make all of the data buffer controllers interchangeable and provide just one set of implementations for all. In practice, there are problems with differing data types (e.g., sample arrays vs. coefficient arrays in the buffers) and there are many special-case considerations. It seems best to make each controller a distinct module, even though there will be some very similar code in each one. *** Compression object structure *** Here is a sketch of the logical structure of the JPEG compression library: |-- Colorspace conversion |-- Preprocessing controller --| | |-- Downsampling Main controller --| | |-- Forward DCT, quantize |-- Coefficient controller --| |-- Entropy encoding This sketch also describes the flow of control (subroutine calls) during typical image data processing. Each of the components shown in the diagram is an "object" which may have several different implementations available. One or more source code files contain the actual implementation(s) of each object. The objects shown above are: * Main controller: buffer controller for the subsampled-data buffer, which holds the preprocessed input data. This controller invokes preprocessing to fill the subsampled-data buffer, and JPEG compression to empty it. There is usually no need for a full-image buffer here; a strip buffer is adequate. * Preprocessing controller: buffer controller for the downsampling input data buffer, which lies between colorspace conversion and downsampling. Note that a unified conversion/downsampling module would probably replace this controller entirely. * Colorspace conversion: converts application image data into the desired JPEG color space; also changes the data from pixel-interleaved layout to separate component planes. Processes one pixel row at a time. * Downsampling: performs reduction of chroma components as required. Optionally may perform pixel-level smoothing as well. Processes a "row group" at a time, where a row group is defined as Vmax pixel rows of each component before downsampling, and Vk sample rows afterwards (Vk differs across components). Some downsampling or smoothing algorithms may require context rows above and below the current row group; the preprocessing controller is responsible for supplying these rows via proper buffering. The downsampler is responsible for edge expansion at the right edge (i.e., extending each sample row to a multiple of 8 samples); but the preprocessing controller is responsible for vertical edge expansion (i.e., duplicating the bottom sample row as needed to make a multiple of 8 rows). * Coefficient controller: buffer controller for the DCT-coefficient data. This controller handles MCU assembly, including insertion of dummy DCT blocks when needed at the right or bottom edge. When performing Huffman-code optimization or emitting a multiscan JPEG file, this controller is responsible for buffering the full image. * Forward DCT and quantization: Perform DCT, quantize, and emit coefficients in zigzag block order. Works on one or more DCT blocks at a time. * Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the coded data to the data destination module. Works on one MCU per call. [Note: the initial proto-v5 implementation deviates from the above sketch in that Huffman-code optimization is done by buffering the image at the main controller, not in the coefficient controller. This implies that the DCT step must be done twice. This is a temporary hack done to support some experiments with variable quantization; it should be fixed before v5 release.] In addition to the above objects, the compression library includes these objects: * Master control: determines the number of passes required, controls overall and per-pass initialization of the other modules. * Marker writing: generates JPEG markers (except for RSTn, which is emitted by the entropy encoder when needed). * Data destination manager: writes the output JPEG datastream to its final destination (e.g., a file). The destination manager supplied with the library knows how to write to a stdio stream; for other behaviors, the surrounding application may provide its own destination manager. * Memory manager: allocates and releases memory, controls virtual arrays (with backing store management, where required). * Error handler: performs formatting and output of error and trace messages; determines handling of nonfatal errors. The surrounding application may override some or all of this object's methods to change error handling. * Progress monitor: supports output of "percent-done" progress reports. This object represents an optional callback to the surrounding application: if wanted, it must be supplied by the application. The error handler, destination manager, and progress monitor objects are defined as separate objects in order to simplify application-specific customization of the JPEG library. A surrounding application may override individual methods or supply its own all-new implementation of one of these objects. The object interfaces for these objects are therefore treated as part of the application interface of the library, whereas the other objects are internal to the library. The error handler and memory manager are shared by JPEG compression and decompression; the progress monitor, if used, may be shared as well. *** Decompression object structure *** Here is a sketch of the logical structure of the JPEG decompression library: |-- Entropy decoding |-- Coefficient controller --| | |-- Dequantize, Inverse DCT Main controller --| | |-- Upsampling |-- Postprocessing controller --| |-- Colorspace conversion |-- Color quantization |-- Color precision reduction As before, this diagram also represents typical control flow. The objects shown are: * Main controller: buffer controller for the subsampled-data buffer, which holds the output of JPEG decompression proper. This controller's primary task is to feed the postprocessing procedure. Some upsampling algorithms may require context rows above and below the current row group; when this is true, the main controller is responsible for managing its buffer so as to make context rows available. In the current design, the main buffer is always a strip buffer; a full-image buffer is never required. * Coefficient controller: buffer controller for the DCT-coefficient data. This controller handles MCU disassembly, including deletion of any dummy DCT blocks at the right or bottom edge. When reading a multiscan JPEG file, this controller is responsible for buffering the full image. (Buffering DCT coefficients, rather than samples, is necessary to support progressive JPEG.) The equivalent of one fully interleaved MCU row of subsampled data is emitted per call, even when the source JPEG file was noninterleaved. * Entropy decoding: Read coded data from the data source module and perform Huffman or arithmetic entropy decoding. Works on one MCU per call. * Dequantization and inverse DCT: like it says. Note, however, that dequantization multiplications are usually performed in the entropy decoder for speed reasons (since the decoder can more readily skip over zeroes). When scaled-down output is asked for, simplified DCT algorithms may be used that emit only 1x1, 2x2, or 4x4 samples per DCT block, not the full 8x8. Works on one DCT block at a time. * Postprocessing controller: buffer controller for the color quantization input buffer, when quantization is in use. (Without quantization, this controller just calls the upsampler.) For two-pass quantization, this controller is responsible for buffering the full-image data. * Upsampling: restores chroma components to full size. (May support more general output rescaling, too. Note that if undersized DCT outputs have been emitted by the DCT module, this module must adjust so that properly sized outputs are created.) Works on one row group at a time. This module also calls the color conversion module, so its top level is effectively a buffer controller for the upsampling->color conversion buffer. However, in all but the highest-quality operating modes, upsampling and color conversion are likely to be merged into a single step. * Colorspace conversion: convert from JPEG color space to output color space, and change data layout from separate component planes to pixel-interleaved. Works on one pixel row at a time. * Color quantization: reduce the data to colormapped form, using either an externally specified colormap or an internally generated one. This module is not used for full-color output. Works on one pixel row at a time; may require two passes to generate a color map. Note that the output will always be a single component representing colormap indexes. In the current design, the output values are JSAMPLEs, so an 8-bit compilation cannot quantize to more than 256 colors. This is unlikely to be a problem in practice. * Color reduction: this module handles color precision reduction, e.g., generating 15-bit color (5 bits/primary) from JPEG's 24-bit output. Not quite clear yet how this should be handled... should we merge it with colorspace conversion??? Note that some high-speed operating modes might condense the entire postprocessing sequence to a single module (upsample, color convert, and quantize in one step). In addition to the above objects, the decompression library includes these objects: * Master control: determines the number of passes required, controls overall and per-pass initialization of the other modules. * Marker reading: decodes JPEG markers (except for RSTn). * Data source manager: supplies the input JPEG datastream. The source manager supplied with the library knows how to read from a stdio stream; for other behaviors, the surrounding application may provide its own source manager. * Memory manager: same as for compression library. * Error handler: same as for compression library. * Progress monitor: same as for compression library. As with compression, the data source manager, error handler, and progress monitor are candidates for replacement by a surrounding application. *** Data formats *** Arrays of pixel sample values will use the following data structure: typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE typedef JSAMPLE *JSAMPROW; ptr to a row of samples typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays The basic element type JSAMPLE will typically be one of unsigned char, (signed) char, or short. Short will be used if samples wider than 8 bits are to be supported (this is a compile-time option). Otherwise, unsigned char is used if possible. If the compiler only supports signed chars, then it is necessary to mask off the value when reading. Thus, all reads of JSAMPLE values should be coded as "GETJSAMPLE(value)", where the macro will be defined as "((value) & 0xFF)" on signed-char machines and "(value)" elsewhere. With these conventions, JSAMPLE values can be assumed to be >= 0. This should simplify correct rounding during downsampling, etc. The JPEG standard's specification that sample values run from -128..127 will be accommodated by subtracting 128 just as the sample value is copied into the source array for the DCT step (this will be an array of signed ints). Similarly, during decompression the output of the IDCT step will be immediately shifted back to 0..255. (NB: different values are required when 12-bit samples are in use. The code should be written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be #defined as 255 and 128 respectively in an 8-bit implementation, and as 4095 and 2048 in a 12-bit implementation.) We use a pointer per row, rather than a two-dimensional JSAMPLE array. This choice costs only a small amount of memory and has several benefits: * Code using the data structure doesn't need to know the allocated width of the rows. This will simplify edge expansion/compression, since we can work in an array that's wider than the logical picture width. * Indexing doesn't require multiplication; this is a performance win on many machines. * Arrays with more than 64K total elements can be supported even on machines where malloc() cannot allocate chunks larger than 64K. * The rows forming a component array may be allocated at different times without extra copying. This trick allows some speedups in smoothing steps that need access to the previous and next rows. Note that each color component is stored in a separate array; we don't use the traditional layout in which the components of a pixel are stored together. This simplifies coding of modules that work on each component independently, because they don't need to know how many components there are. Furthermore, we can read or write each component to a temporary file independently, which is helpful when dealing with noninterleaved JPEG files. A specific sample value will be accessed by code such as GETJSAMPLE(image[colorcomponent][row][col]) where col is measured from the image left edge, but row is measured from the first sample row currently in memory. Either of the first two indexings can be precomputed by copying the relevant pointer. Since most image-processing applications prefer to work on images in which the components of a pixel are stored together, the data passed to or from the surrounding application will use the traditional convention: a single pixel is represented by N consecutive JSAMPLE values, and an image row is an array of (# of color components)*(image width) JSAMPLEs. One or more rows of data can be represented by a pointer of type JSAMPARRAY in this scheme. This scheme will be converted to component-wise storage inside the JPEG library. (Applications that want to skip JPEG preprocessing or postprocessing will have to contend with component-wise storage.) Arrays of frequency-coefficient values will use the following data structure: typedef short JCOEF; a 16-bit signed integer typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays The underlying type is at least a 16-bit signed integer; while "short" is big enough on all machines of interest, on some machines it is preferable to use "int" for speed reasons, despite the storage cost. Coefficients are grouped into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than "8" and "64"). The contents of a block may be either in "natural" or zigzagged order, and may be true values or divided by the quantization coefficients, depending on where the block is in the processing pipeline. Notice that the allocation unit is now a row of 8x8 blocks, corresponding to eight rows of samples. Otherwise the structure is much the same as for samples, and for the same reasons. On machines where malloc() can't handle a request bigger than 64Kb, this data structure limits us to rows of less than 512 JBLOCKs, or a picture width of 4000+ pixels. This seems an acceptable restriction. On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW) must be declared as "far" pointers, but the upper levels can be "near" (implying that the pointer lists are allocated in the DS segment). We use a #define symbol FAR, which expands to the "far" keyword when compiling on 80x86 machines and to nothing elsewhere. *** Suspendable processing *** In some applications it is desirable to use the JPEG library as an incremental, memory-to-memory filter. In this situation the data source or destination may be a limited-size buffer, and we can't rely on being able to empty or refill the buffer at arbitrary times. Instead the application would like to have control return from the library at buffer overflow/underrun, and then resume compression or decompression at a later time. This scenario is supported for simple cases, namely, single-pass processing of single-scan JPEG files. (For anything more complex, we recommend that the application "bite the bullet" and develop real multitasking capability.) The libjpeg.doc file goes into more detail about the usage and limitations of this capability; here we address the implications for library structure. The essence of the problem is that the entropy codec (coder or decoder) must be prepared to stop at arbitrary times. In turn, the controllers that call the entropy codec must be able to stop before having produced or consumed all the data that they normally would handle in one call. That part is reasonably straightforward: we make the controller call interfaces include "progress counters" which indicate the number of data chunks successfully processed, and we require callers to test the counter rather than just assume all of the data was processed. Rather than trying to restart at an arbitrary point, the current Huffman codecs are designed to restart at the beginning of the current MCU after a suspension due to buffer overflow/underrun. At the start of each call, the codec's internal state is loaded from permanent storage (in the JPEG object structures) into local variables. On successful completion of the MCU, the permanent state is updated. (This copying is not very expensive, and may even lead to *improved* performance if the local variables can be registerized.) If a suspension occurs, the codec simply returns without updating the state, thus effectively reverting to the start of the MCU. Note that this implies leaving some data unprocessed in the source/destination buffer (ie, the compressed partial MCU). The data source/destination module interfaces are specified so as to make this possible. This also implies that the data buffer must be large enough to hold a worst-case compressed MCU; a couple thousand bytes should be enough. This design would probably not work for an arithmetic codec, since its modifiable state is quite large and couldn't be copied cheaply. Instead it would have to suspend and resume exactly at the point of the buffer end. Also, a progressive JPEG decoder would have some problems with having already updated the output DCT coefficient buffer, since progressive decoding depends on the prior state of the coefficient buffer. This case might also have to be handled by exact restart. Currently I expect that IJG will just not support suspendable operation in these cases (when and if we implement them at all). The JPEG marker reader is also designed to cope with suspension at an arbitrary point. It does so by backing up to the start of the marker parameter segment, so the data buffer must be big enough to hold the largest marker of interest. Again, a couple K should be adequate. (A special "skip" convention is used to bypass COM and APPn markers, so these can be larger than the buffer size without causing problems; otherwise a 64K buffer would be needed in the worst case.) The JPEG marker writer currently does *not* cope with suspension. I feel that this is not necessary; it is much easier simply to require the application to ensure there is enough buffer space before starting. (An empty 2K buffer is more than sufficient for the header markers; and ensuring there are a dozen or two bytes available before calling jpeg_finish_compress() will suffice for the trailer.) Again, this would not work for writing multi-scan JPEG files, but we simply do not intend to support that capability with suspension. *** Memory manager services *** The JPEG library's memory manager controls allocation and deallocation of memory, and it manages large "virtual" data arrays on machines where the operating system does not provide virtual memory. Note that the same memory manager serves both compression and decompression operations. In all cases, allocated objects are tied to a particular compression or decompression master record, and they will be released when that master record is destroyed. The memory manager does not provide explicit deallocation of objects. Instead, objects are created in "pools" of free storage, and a whole pool can be freed at once. This approach helps prevent storage-leak bugs, and it speeds up operations whenever malloc/free are slow (as they often are). The pools can be regarded as lifetime identifiers for objects. Two pools/lifetimes are defined: * JPOOL_PERMANENT lasts until master record is destroyed * JPOOL_IMAGE lasts until done with image (JPEG datastream) Permanent lifetime is used for parameters and tables that should be carried across from one datastream to another; this includes all application-visible parameters. Image lifetime is used for everything else. (A third lifetime, JPOOL_PASS = one processing pass, was originally planned. However it was dropped as not being worthwhile. The actual usage patterns are such that the peak memory usage would be about the same anyway; and having per-pass storage substantially complicates the virtual memory allocation rules --- see below.) The memory manager deals with three kinds of object: 1. "Small" objects. Typically these require no more than 10K-20K total. 2. "Large" objects. These may require tens to hundreds of K depending on image size. Semantically they behave the same as small objects, but we distinguish them for two reasons: * On MS-DOS machines, large objects are referenced by FAR pointers, small objects by NEAR pointers. * Pool allocation heuristics may differ for large and small objects. Note that individual "large" objects cannot exceed the size allowed by type size_t, which may be 64K or less on some machines. 3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs (typically large enough for the entire image being processed). The memory manager provides stripwise access to these arrays. On machines without virtual memory, the rest of the array may be swapped out to a temporary file. (Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large objects for the data proper and small objects for the row pointers. For convenience and speed, the memory manager provides single routines to create these structures. Similarly, virtual arrays include a small control block and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.) In the present implementation, virtual arrays are only permitted to have image lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is not very useful since a virtual array's raison d'etre is to store data for multiple passes through the image.) We also expect that only "small" objects will be given permanent lifespan, though this restriction is not required by the memory manager. In a non-virtual-memory machine, some performance benefit can be gained by making the in-memory buffers for virtual arrays be as large as possible. (For small images, the buffers might fit entirely in memory, so blind swapping would be very wasteful.) The memory manager will adjust the height of the buffers to fit within a prespecified maximum memory usage. In order to do this in a reasonably optimal fashion, the manager needs to allocate all of the virtual arrays at once. Therefore, there isn't a one-step allocation routine for virtual arrays; instead, there is a "request" routine that simply allocates the control block, and a "realize" routine (called just once) that determines space allocation and creates all of the actual buffers. The realize routine must allow for space occupied by non-virtual large objects. (We don't bother to factor in the space needed for small objects, on the grounds that it isn't worth the trouble.) To support all this, we establish the following protocol for doing business with the memory manager: 1. Modules must request virtual arrays (which may have only image lifespan) during the global selection phase, i.e., in their jinit_xxx routines. 2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be allocated at global selection time. 3. realize_virt_arrays will be called at the completion of global selection. The above conventions ensure that sufficient information is available for it to choose a good size for virtual array buffers. Small objects of any lifespan may be allocated at any time. We expect that the total space used for small objects will be small enough to be negligible in the realize_virt_arrays computation. In a virtual-memory machine, we simply pretend that the available space is infinite, thus causing realize_virt_arrays to decide that it can allocate all the virtual arrays as full-size in-memory buffers. The overhead of the virtual-array access protocol is very small when no swapping occurs. *** Memory manager internal structure *** To isolate system dependencies as much as possible, we have broken the memory manager into two parts. There is a reasonably system-independent "front end" (jmemmgr.c) and a "back end" that contains only the code likely to change across systems. All of the memory management methods outlined above are implemented by the front end. The back end provides the following routines for use by the front end (none of these routines are known to the rest of the JPEG code): jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown jpeg_get_small, jpeg_free_small interface to malloc and free library routines (or their equivalents) jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines; else usually the same as jpeg_get_small/jpeg_free_small jpeg_mem_available estimate available memory jpeg_open_backing_store create a backing-store object read_backing_store, manipulate a backing-store object write_backing_store, close_backing_store On some systems there will be more than one type of backing-store object (specifically, in MS-DOS a backing store file might be an area of extended memory as well as a disk file). jpeg_open_backing_store is responsible for choosing how to implement a given object. The read/write/close routines are method pointers in the structure that describes a given object; this lets them be different for different object types. It may be necessary to ensure that backing store objects are explicitly released upon abnormal program termination. For example, MS-DOS won't free extended memory by itself. To support this, we will expect the main program or surrounding application to arrange to call self_destruct (typically via jpeg_destroy) upon abnormal termination. This may require a SIGINT signal handler or equivalent. We don't want to have the back end module install its own signal handler, because that would pre-empt the surrounding application's ability to control signal handling. The IJG distribution includes several memory manager back end implementations. Usually the same back end should be suitable for all applications on a given system, but it is possible for an application to supply its own back end at need. *** Implications of DNL marker *** Some JPEG files may use a DNL marker to postpone definition of the image height (this would be useful for a fax-like scanner's output, for instance). In these files the SOF marker claims the image height is 0, and you only find out the true image height at the end of the first scan. We could read these files as follows: 1. Upon seeing zero image height, replace it by 65535 (the maximum allowed). 2. When the DNL is found, update the image height in the global image descriptor. This implies that control modules must avoid making copies of the image height, and must re-test for termination after each MCU row. This would be easy enough to do. In cases where image-size data structures are allocated, this approach will result in very inefficient use of virtual memory or much-larger-than-necessary temporary files. This seems acceptable for something that probably won't be a mainstream usage. People might have to forgo use of memory-hogging options (such as two-pass color quantization or noninterleaved JPEG files) if they want efficient conversion of such files. (One could improve efficiency by demanding a user-supplied upper bound for the height, less than 65536; in most cases it could be much less.) The standard also permits the SOF marker to overestimate the image height, with a DNL to give the true, smaller height at the end of the first scan. This would solve the space problems if the overestimate wasn't too great. However, it implies that you don't even know whether DNL will be used. This leads to a couple of very serious objections: 1. Testing for a DNL marker must occur in the inner loop of the decompressor's Huffman decoder; this implies a speed penalty whether the feature is used or not. 2. There is no way to hide the last-minute change in image height from an application using the decoder. Thus *every* application using the IJG library would suffer a complexity penalty whether it cared about DNL or not. We currently do not support DNL because of these problems. A different approach is to insist that DNL-using files be preprocessed by a separate program that reads ahead to the DNL, then goes back and fixes the SOF marker. This is a much simpler solution and is probably far more efficient. Even if one wants piped input, buffering the first scan of the JPEG file needs a lot smaller temp file than is implied by the maximum-height method. For this approach we'd simply treat DNL as a no-op in the decompressor (at most, check that it matches the SOF image height). We will not worry about making the compressor capable of outputting DNL. Something similar to the first scheme above could be applied if anyone ever wants to make that work. \ No newline at end of file diff --git a/Independent JPEG Group/testimg.jpg b/Independent JPEG Group/testimg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..580af71594c21e8d15d5f8d7e8f8f1280717a605 GIT binary patch literal 4374 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 z z64Y(Td~A_5`07|XF$SbR%>9LvG+LKs3cTb++0_~K?ozZzEB>7T{im>?)8RRqMI(=S+1X=3q0$^ z5S7{Bgbo5rOtCf7Xonmkmo3igQXM!0fbQfK+%fFq3=BqkFTul83&nrGJ literal 0 HcmV?d00001 diff --git a/Independent JPEG Group/usage.doc b/Independent JPEG Group/usage.doc new file mode 100644 index 0000000..ed766c6 --- /dev/null +++ b/Independent JPEG Group/usage.doc @@ -0,0 +1 @@ +USAGE instructions for the Independent JPEG Group's JPEG software ================================================================= This file describes usage of the JPEG conversion programs "cjpeg" and "djpeg". (See the other documentation files if you wish to use the JPEG library within other programs.) If you are on a Unix machine you may prefer to read the Unix-style manual pages in files cjpeg.1 and djpeg.1. INTRODUCTION These programs implement JPEG image compression and decompression. JPEG (pronounced "jay-peg") is a standardized compression method for full-color and gray-scale images. JPEG is designed to handle "real-world" scenes, for example scanned photographs. Cartoons, line drawings, and other non-realistic images are not JPEG's strong suit; on this sort of material you may get poor image quality and/or little compression. JPEG is lossy, meaning that the output image is not necessarily identical to the input image. Hence you should not use JPEG if you have to have identical output bits. However, on typical real-world images, very good compression levels can be obtained with no visible change, and amazingly high compression is possible if you can tolerate a low-quality image. You can trade off image quality against file size by adjusting the compressor's "quality" setting. GENERAL USAGE We provide two programs, cjpeg to compress an image file into JPEG format, and djpeg to decompress a JPEG file back into a conventional image format. On Unix-like systems, you say: cjpeg [switches] [imagefile] >jpegfile or djpeg [switches] [jpegfile] >imagefile The programs read the specified input file, or standard input if none is named. They always write to standard output (with trace/error messages to standard error). These conventions are handy for piping images between programs. On most non-Unix systems, you say: cjpeg [switches] imagefile jpegfile or djpeg [switches] jpegfile imagefile i.e., both the input and output files are named on the command line. This style is a little more foolproof, and it loses no functionality if you don't have pipes. (You can get this style on Unix too, if you prefer, by defining TWO_FILE_COMMANDLINE when you compile the programs; see install.doc.) You can also say: cjpeg [switches] -outfile jpegfile imagefile or djpeg [switches] -outfile imagefile jpegfile This syntax works on all systems, so it is useful for scripts. The currently supported image file formats are: PPM (PBMPLUS color format), PGM (PBMPLUS gray-scale format), GIF, Targa, and RLE (Utah Raster Toolkit format). (RLE is supported only if the URT library is available.) cjpeg recognizes the input image format automatically, with the exception of some Targa-format files. You have to tell djpeg which format to generate. JPEG files are in the defacto standard JFIF file format. There are other, less widely used JPEG-based file formats, but we don't support them. All switch names may be abbreviated; for example, -grayscale may be written -gray or -gr. Most of the "basic" switches can be abbreviated to as little as one letter. Upper and lower case are equivalent (-GIF is the same as -gif). British spellings are also accepted (e.g., -greyscale), though for brevity these are not mentioned below. CJPEG DETAILS The basic command line switches for cjpeg are: -quality N Scale quantization tables to adjust image quality. Quality is 0 (worst) to 100 (best); default is 75. (See below for more info.) -grayscale Create monochrome JPEG file from color input. Be sure to use this switch when compressing a grayscale GIF file, because cjpeg isn't bright enough to notice whether a GIF file uses only shades of gray. By saying -grayscale, you'll get a smaller JPEG file that takes less time to process. -optimize Perform optimization of entropy encoding parameters. Without this, default encoding parameters are used. -optimize usually makes the JPEG file a little smaller, but cjpeg runs somewhat slower and needs much more memory. Image quality and speed of decompression are unaffected by -optimize. -targa Input file is Targa format. Targa files that contain an "identification" field will not be automatically recognized by cjpeg; for such files you must specify -targa to make cjpeg treat the input as Targa format. The -quality switch lets you trade off compressed file size against quality of the reconstructed image: the higher the quality setting, the larger the JPEG file, and the closer the output image will be to the original input. Normally you want to use the lowest quality setting (smallest file) that decompresses into something visually indistinguishable from the original image. For this purpose the quality setting should be between 50 and 95; the default of 75 is often about right. If you see defects at -quality 75, then go up 5 or 10 counts at a time until you are happy with the output image. (The optimal setting will vary from one image to another.) -quality 100 will generate a quantization table of all 1's, eliminating loss in the quantization step (but there is still information loss in subsampling, as well as roundoff error). This setting is mainly of interest for experimental purposes. Quality values above about 95 are NOT recommended for normal use; the compressed file size goes up dramatically for hardly any gain in output image quality. In the other direction, quality values below 50 will produce very small files of low image quality. Settings around 5 to 10 might be useful in preparing an index of a large image library, for example. Try -quality 2 (or so) for some amusing Cubist effects. (Note: quality values below about 25 generate 2-byte quantization tables, which are considered optional in the JPEG standard. cjpeg emits a warning message when you give such a quality value, because some commercial JPEG programs may be unable to decode the resulting file. Use -baseline if you need to ensure compatibility at low quality values.) Switches for advanced users: -maxmemory N Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. -restart N Emit a JPEG restart marker every N MCU rows, or every N MCU blocks if "B" is attached to the number. -restart 0 (the default) means no restart markers. -smooth N Smooth the input image to eliminate dithering noise. N, ranging from 1 to 100, indicates the strength of smoothing. 0 (the default) means no smoothing. -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. The -restart option inserts extra markers that allow a JPEG decoder to resynchronize after a transmission error. Without restart markers, any damage to a compressed file will usually ruin the image from the point of the error to the end of the image; with restart markers, the damage is usually confined to the portion of the image up to the next restart marker. Of course, the restart markers occupy extra space. We recommend -restart 1 for images that will be transmitted across unreliable networks such as Usenet. The -smooth option filters the input to eliminate fine-scale noise. This is often useful when converting GIF files to JPEG: a moderate smoothing factor of 10 to 50 gets rid of dithering patterns in the input file, resulting in a smaller JPEG file and a better-looking image. Too large a smoothing factor will visibly blur the image, however. Switches for wizards: -arithmetic Use arithmetic coding rather than Huffman coding. (Not currently supported for legal reasons.) -baseline Force a baseline JPEG file to be generated. This clamps quantization values to 8 bits even at low quality settings. -nointerleave Generate noninterleaved JPEG file (not yet supported). -qtables file Use the quantization tables given in the specified file. The file should contain one to four tables (64 values each) as plain text. Comments preceded by '#' may be included in the file. The tables are implicitly numbered 0,1,etc. If -quality N is also specified, the values in the file are scaled according to cjpeg's quality scaling curve. -qslots N[,...] Select which quantization table to use for each color component. By default, table 0 is used for luminance and table 1 for chrominance components. -sample HxV[,...] Set JPEG sampling factors. If you specify fewer H/V pairs than there are components, the remaining components are set to 1x1 sampling. The default setting is equivalent to "-sample 2x2". The "wizard" switches are intended for experimentation with JPEG. If you don't know what you are doing, DON'T USE THEM. You can easily produce files with worse image quality and/or poorer compression than you'll get from the default settings. Furthermore, these switches should not be used when making files intended for general use, because not all JPEG implementations will support unusual JPEG parameter settings. DJPEG DETAILS The basic command line switches for djpeg are: -colors N Reduce image to at most N colors. This reduces the or -quantize N number of colors used in the output image, so that it can be displayed on a colormapped display or stored in a colormapped file format. For example, if you have an 8-bit display, you'd need to reduce to 256 or fewer colors. (-colors is the recommended name, -quantize is provided only for backwards compatibility.) -grayscale Force gray-scale output even if JPEG file is color. Useful for viewing on monochrome displays; also, djpeg runs noticeably faster in this mode. -scale M/N Scale the output image by a factor M/N. Currently the scale factor must be 1/1, 1/2, 1/4, or 1/8. Scaling is handy if the image is larger than your screen; also, djpeg runs much faster when scaling down the output. -gif Select GIF output format. Since GIF does not support more than 256 colors, -colors 256 is assumed (unless you specify a smaller number of colors). -pnm Select PBMPLUS (PPM/PGM) output format (this is the default format). PGM is emitted if the JPEG file is gray-scale or if -grayscale is specified; otherwise PPM is emitted. -rle Select RLE output format. (Requires URT library.) -targa Select Targa output format. Gray-scale format is emitted if the JPEG file is gray-scale or if -grayscale is specified; otherwise, colormapped format is emitted if -colors is specified; otherwise, 24-bit full-color format is emitted. Switches for advanced users: -blocksmooth Perform cross-block smoothing. This is slow, quite memory-intensive, and only seems to improve the image at very low quality settings (-quality 10 to 20 or so). At normal quality settings it may make things worse. -maxmemory N Set limit for amount of memory to use in processing large images. Value is in thousands of bytes, or millions of bytes if "M" is attached to the number. For example, -max 4m selects 4000000 bytes. If more space is needed, temporary files will be used. -nodither Do not use dithering in color quantization. By default, Floyd-Steinberg dithering is applied when quantizing colors, but on some images dithering may result in objectionable "graininess". If that happens, you can turn off dithering with -nodither. -nosmooth Use a faster, lower-quality upsampling routine. -onepass Use one-pass instead of two-pass color quantization. The one-pass method is faster and needs less memory, but it produces a lower-quality image. -onepass is ignored unless you also say -colors N. Also, the one-pass method is always used for gray-scale output (the two-pass method is no improvement then). -verbose Enable debug printout. More -v's give more printout. or -debug Also, version information is printed at startup. HINTS FOR CJPEG Color GIF files are not the ideal input for JPEG; JPEG is really intended for compressing full-color (24-bit) images. In particular, don't try to convert cartoons, line drawings, and other images that have only a few distinct colors. GIF works great on these, JPEG does not. If you want to convert a GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options to get a satisfactory conversion. -smooth 10 or so is often helpful. Avoid running an image through a series of JPEG compression/decompression cycles. Image quality loss will accumulate; after ten or so cycles the image may be noticeably worse than it was after one cycle. It's best to use a lossless format while manipulating an image, then convert to JPEG format when you are ready to file the image away. The -optimize option to cjpeg is worth using when you are making a "final" version for posting or archiving. It's also a win when you are using low quality settings to make very small JPEG files; the percentage improvement is often a lot more than it is on larger files. HINTS FOR DJPEG To get a quick preview of an image, use the -grayscale and/or -scale switches. "-grayscale -scale 1/8" is the fastest option. djpeg with two-pass color quantization requires a good deal of memory; on MS-DOS machines it may run out of memory even with -maxmemory 0. In that case you can still decompress, with some loss of image quality, by specifying -onepass for one-pass quantization. HINTS FOR BOTH PROGRAMS If more space is needed than will fit in the available main memory (as determined by -maxmemory), temporary files will be used. (MS-DOS versions will try to get extended or expanded memory first.) The temporary files are often rather large: in typical cases they occupy three bytes per pixel, for example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough free disk space, leave out -optimize (for cjpeg) or specify -onepass (for djpeg). On MS-DOS, the temporary files are created in the directory named by the TMP or TEMP environment variable, or in the current directory if neither of those exist. Amiga implementations put the temp files in the directory named by JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free space. The default memory usage limit (-maxmemory) is set when the software is compiled. If you get an "insufficient memory" error, try specifying a smaller -maxmemory value, even -maxmemory 0 to use the absolute minimum space. You may want to recompile with a smaller default value if this happens often. On machines that have "environment" variables, you can define the environment variable JPEGMEM to set the default memory limit. The value is specified as described for the -maxmemory switch. JPEGMEM overrides the default value specified when the program was compiled, and itself is overridden by an explicit -maxmemory switch. On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to use. (Extended or expanded memory is also used if available.) Most DOS-specific versions of this software do their own memory space estimation and do not need you to specify -maxmemory. \ No newline at end of file diff --git a/Independent JPEG Group/wrgif.c b/Independent JPEG Group/wrgif.c new file mode 100644 index 0000000..e253711 --- /dev/null +++ b/Independent JPEG Group/wrgif.c @@ -0,0 +1 @@ +/* * wrgif.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write output images in GIF format. * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume output to * an ordinary stdio stream. */ /* * This code is loosely based on ppmtogif from the PBMPLUS distribution * of Feb. 1991. That file contains the following copyright notice: * Based on GIFENCODE by David Rowley . * Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al. * Copyright (C) 1989 by Jef Poskanzer. * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. This software is provided "as is" without express or * implied warranty. * * We are also required to state that * "The Graphics Interchange Format(c) is the Copyright property of * CompuServe Incorporated. GIF(sm) is a Service Mark property of * CompuServe Incorporated." */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #ifdef GIF_SUPPORTED #define MAX_LZW_BITS 12 /* maximum LZW code size (4096 symbols) */ typedef INT16 code_int; /* must hold -1 .. 2**MAX_LZW_BITS */ #define LZW_TABLE_SIZE ((code_int) 1 << MAX_LZW_BITS) #define HSIZE 5003 /* hash table size for 80% occupancy */ typedef int hash_int; /* must hold -2*HSIZE..2*HSIZE */ #define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1) /* * The LZW hash table consists of two parallel arrays: * hash_code[i] code of symbol in slot i, or 0 if empty slot * hash_value[i] symbol's value; undefined if empty slot * where slot values (i) range from 0 to HSIZE-1. The symbol value is * its prefix symbol's code concatenated with its suffix character. * * Algorithm: use open addressing double hashing (no chaining) on the * prefix code / suffix character combination. We do a variant of Knuth's * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime * secondary probe. * * The hash_value[] table is allocated from FAR heap space since it would * use up rather a lot of the near data space in a PC. */ typedef INT32 hash_entry; /* must hold (code_int<<8) | byte */ #define HASH_ENTRY(prefix,suffix) ((((hash_entry) (prefix)) << 8) | (suffix)) /* Private version of data destination object */ typedef struct { struct djpeg_dest_struct pub; /* public fields */ j_decompress_ptr cinfo; /* back link saves passing separate parm */ /* State for packing variable-width codes into a bitstream */ int n_bits; /* current number of bits/code */ code_int maxcode; /* maximum code, given n_bits */ int init_bits; /* initial n_bits ... restored after clear */ INT32 cur_accum; /* holds bits not yet output */ int cur_bits; /* # of bits in cur_accum */ /* LZW string construction */ code_int waiting_code; /* symbol not yet output; may be extendable */ boolean first_byte; /* if TRUE, waiting_code is not valid */ /* State for LZW code assignment */ code_int ClearCode; /* clear code (doesn't change) */ code_int EOFCode; /* EOF code (ditto) */ code_int free_code; /* first not-yet-used symbol code */ /* LZW hash table */ code_int *hash_code; /* => hash table of symbol codes */ hash_entry FAR *hash_value; /* => hash table of symbol values */ /* GIF data packet construction buffer */ int bytesinpkt; /* # of bytes in current packet */ char packetbuf[256]; /* workspace for accumulating packet */ } gif_dest_struct; typedef gif_dest_struct * gif_dest_ptr; /* * Routines to package compressed data bytes into GIF data blocks. * A data block consists of a count byte (1..255) and that many data bytes. */ LOCAL void flush_packet (gif_dest_ptr dinfo) /* flush any accumulated data */ { if (dinfo->bytesinpkt > 0) { /* never write zero-length packet */ dinfo->packetbuf[0] = (char) dinfo->bytesinpkt++; if (JFWRITE(dinfo->pub.output_file, dinfo->packetbuf, dinfo->bytesinpkt) != (size_t) dinfo->bytesinpkt) ERREXIT(dinfo->cinfo, JERR_FILE_WRITE); dinfo->bytesinpkt = 0; } } /* Add a character to current packet; flush to disk if necessary */ #define CHAR_OUT(dinfo,c) \ { (dinfo)->packetbuf[++(dinfo)->bytesinpkt] = (char) (c); \ if ((dinfo)->bytesinpkt >= 255) \ flush_packet(dinfo); \ } /* Routine to convert variable-width codes into a byte stream */ LOCAL void output (gif_dest_ptr dinfo, code_int code) /* Emit a code of n_bits bits */ /* Uses cur_accum and cur_bits to reblock into 8-bit bytes */ { dinfo->cur_accum |= ((INT32) code) << dinfo->cur_bits; dinfo->cur_bits += dinfo->n_bits; while (dinfo->cur_bits >= 8) { CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF); dinfo->cur_accum >>= 8; dinfo->cur_bits -= 8; } /* * If the next entry is going to be too big for the code size, * then increase it, if possible. We do this here to ensure * that it's done in sync with the decoder's codesize increases. */ if (dinfo->free_code > dinfo->maxcode) { dinfo->n_bits++; if (dinfo->n_bits == MAX_LZW_BITS) dinfo->maxcode = LZW_TABLE_SIZE; /* free_code will never exceed this */ else dinfo->maxcode = MAXCODE(dinfo->n_bits); } } /* The LZW algorithm proper */ LOCAL void clear_hash (gif_dest_ptr dinfo) /* Fill the hash table with empty entries */ { /* It's sufficient to zero hash_code[] */ MEMZERO(dinfo->hash_code, HSIZE * SIZEOF(code_int)); } LOCAL void clear_block (gif_dest_ptr dinfo) /* Reset compressor and issue a Clear code */ { clear_hash(dinfo); /* delete all the symbols */ dinfo->free_code = dinfo->ClearCode + 2; output(dinfo, dinfo->ClearCode); /* inform decoder */ dinfo->n_bits = dinfo->init_bits; /* reset code size */ dinfo->maxcode = MAXCODE(dinfo->n_bits); } LOCAL void compress_init (gif_dest_ptr dinfo, int i_bits) /* Initialize LZW compressor */ { /* init all the state variables */ dinfo->n_bits = dinfo->init_bits = i_bits; dinfo->maxcode = MAXCODE(dinfo->n_bits); dinfo->ClearCode = ((code_int) 1 << (i_bits - 1)); dinfo->EOFCode = dinfo->ClearCode + 1; dinfo->free_code = dinfo->ClearCode + 2; dinfo->first_byte = TRUE; /* no waiting symbol yet */ /* init output buffering vars */ dinfo->bytesinpkt = 0; dinfo->cur_accum = 0; dinfo->cur_bits = 0; /* clear hash table */ clear_hash(dinfo); /* GIF specifies an initial Clear code */ output(dinfo, dinfo->ClearCode); } LOCAL void compress_byte (gif_dest_ptr dinfo, int c) /* Accept and compress one 8-bit byte */ { register hash_int i; register hash_int disp; register hash_entry probe_value; if (dinfo->first_byte) { /* need to initialize waiting_code */ dinfo->waiting_code = c; dinfo->first_byte = FALSE; return; } /* Probe hash table to see if a symbol exists for * waiting_code followed by c. * If so, replace waiting_code by that symbol and return. */ i = ((hash_int) c << (MAX_LZW_BITS-8)) + dinfo->waiting_code; /* i is less than twice 2**MAX_LZW_BITS, therefore less than twice HSIZE */ if (i >= HSIZE) i -= HSIZE; probe_value = HASH_ENTRY(dinfo->waiting_code, c); if (dinfo->hash_code[i] != 0) { /* is first probed slot empty? */ if (dinfo->hash_value[i] == probe_value) { dinfo->waiting_code = dinfo->hash_code[i]; return; } if (i == 0) /* secondary hash (after G. Knott) */ disp = 1; else disp = HSIZE - i; while (1) { i -= disp; if (i < 0) i += HSIZE; if (dinfo->hash_code[i] == 0) break; /* hit empty slot */ if (dinfo->hash_value[i] == probe_value) { dinfo->waiting_code = dinfo->hash_code[i]; return; } } } /* here when hashtable[i] is an empty slot; desired symbol not in table */ output(dinfo, dinfo->waiting_code); if (dinfo->free_code < LZW_TABLE_SIZE) { dinfo->hash_code[i] = dinfo->free_code++; /* add symbol to hashtable */ dinfo->hash_value[i] = probe_value; } else clear_block(dinfo); dinfo->waiting_code = c; } LOCAL void compress_term (gif_dest_ptr dinfo) /* Clean up at end */ { /* Flush out the buffered code */ if (! dinfo->first_byte) output(dinfo, dinfo->waiting_code); /* Send an EOF code */ output(dinfo, dinfo->EOFCode); /* Flush the bit-packing buffer */ if (dinfo->cur_bits > 0) { CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF); } /* Flush the packet buffer */ flush_packet(dinfo); } /* GIF header construction */ LOCAL void put_word (gif_dest_ptr dinfo, unsigned int w) /* Emit a 16-bit word, LSB first */ { putc(w & 0xFF, dinfo->pub.output_file); putc((w >> 8) & 0xFF, dinfo->pub.output_file); } LOCAL void put_3bytes (gif_dest_ptr dinfo, int val) /* Emit 3 copies of same byte value --- handy subr for colormap construction */ { putc(val, dinfo->pub.output_file); putc(val, dinfo->pub.output_file); putc(val, dinfo->pub.output_file); } LOCAL void emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap) /* Output the GIF file header, including color map */ /* If colormap==NULL, synthesize a gray-scale colormap */ { int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte; int cshift = dinfo->cinfo->data_precision - 8; int i; if (num_colors > 256) ERREXIT1(dinfo->cinfo, JERR_TOO_MANY_COLORS, num_colors); /* Compute bits/pixel and related values */ BitsPerPixel = 1; while (num_colors > (1 << BitsPerPixel)) BitsPerPixel++; ColorMapSize = 1 << BitsPerPixel; if (BitsPerPixel <= 1) InitCodeSize = 2; else InitCodeSize = BitsPerPixel; /* * Write the GIF header. * Note that we generate a plain GIF87 header for maximum compatibility. */ putc('G', dinfo->pub.output_file); putc('I', dinfo->pub.output_file); putc('F', dinfo->pub.output_file); putc('8', dinfo->pub.output_file); putc('7', dinfo->pub.output_file); putc('a', dinfo->pub.output_file); /* Write the Logical Screen Descriptor */ put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); put_word(dinfo, (unsigned int) dinfo->cinfo->output_height); FlagByte = 0x80; /* Yes, there is a global color table */ FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */ FlagByte |= (BitsPerPixel-1); /* size of global color table */ putc(FlagByte, dinfo->pub.output_file); putc(0, dinfo->pub.output_file); /* Background color index */ putc(0, dinfo->pub.output_file); /* Reserved (aspect ratio in GIF89) */ /* Write the Global Color Map */ /* If the color map is more than 8 bits precision, */ /* we reduce it to 8 bits by shifting */ for (i=0; i < ColorMapSize; i++) { if (i < num_colors) { if (colormap != NULL) { if (dinfo->cinfo->out_color_space == JCS_RGB) { /* Normal case: RGB color map */ putc(GETJSAMPLE(colormap[0][i]) >> cshift, dinfo->pub.output_file); putc(GETJSAMPLE(colormap[1][i]) >> cshift, dinfo->pub.output_file); putc(GETJSAMPLE(colormap[2][i]) >> cshift, dinfo->pub.output_file); } else { /* Grayscale "color map": possible if quantizing grayscale image */ put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift); } } else { /* Create a gray-scale map of num_colors values, range 0..255 */ put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1)); } } else { /* fill out the map to a power of 2 */ put_3bytes(dinfo, 0); } } /* Write image separator and Image Descriptor */ putc(',', dinfo->pub.output_file); /* separator */ put_word(dinfo, 0); /* left/top offset */ put_word(dinfo, 0); put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); /* image size */ put_word(dinfo, (unsigned int) dinfo->cinfo->output_height); /* flag byte: not interlaced, no local color map */ putc(0x00, dinfo->pub.output_file); /* Write Initial Code Size byte */ putc(InitCodeSize, dinfo->pub.output_file); /* Initialize for LZW compression of image data */ compress_init(dinfo, InitCodeSize+1); } /* * Startup: write the file header. */ METHODDEF void start_output (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) { gif_dest_ptr dest = (gif_dest_ptr) dinfo; if (cinfo->quantize_colors) emit_header(dest, cinfo->actual_number_of_colors, cinfo->colormap); else emit_header(dest, 256, (JSAMPARRAY) NULL); } /* * Write some pixel data. * In this module rows_supplied will always be 1. */ METHODDEF void put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied) { gif_dest_ptr dest = (gif_dest_ptr) dinfo; register JSAMPROW ptr; register JDIMENSION col; ptr = dest->pub.buffer[0]; for (col = cinfo->output_width; col > 0; col--) { compress_byte(dest, GETJSAMPLE(*ptr++)); } } /* * Finish up at the end of the file. */ METHODDEF void finish_output (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) { gif_dest_ptr dest = (gif_dest_ptr) dinfo; /* Flush LZW mechanism */ compress_term(dest); /* Write a zero-length data block to end the series */ putc(0, dest->pub.output_file); /* Write the GIF terminator mark */ putc(';', dest->pub.output_file); /* Make sure we wrote the output file OK */ fflush(dest->pub.output_file); if (ferror(dest->pub.output_file)) ERREXIT(cinfo, JERR_FILE_WRITE); } /* * The module selection routine for GIF format output. */ GLOBAL djpeg_dest_ptr jinit_write_gif (j_decompress_ptr cinfo) { gif_dest_ptr dest; /* Create module interface object, fill in method pointers */ dest = (gif_dest_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(gif_dest_struct)); dest->cinfo = cinfo; /* make back link for subroutines */ dest->pub.start_output = start_output; dest->pub.put_pixel_rows = put_pixel_rows; dest->pub.finish_output = finish_output; if (cinfo->out_color_space != JCS_GRAYSCALE && cinfo->out_color_space != JCS_RGB) ERREXIT(cinfo, JERR_GIF_COLORSPACE); /* Force quantization if color or if > 8 bits input */ if (cinfo->out_color_space != JCS_GRAYSCALE || cinfo->data_precision > 8) { /* Force quantization to at most 256 colors */ cinfo->quantize_colors = TRUE; if (cinfo->desired_number_of_colors > 256) cinfo->desired_number_of_colors = 256; } /* Calculate output image dimensions so we can allocate space */ jpeg_calc_output_dimensions(cinfo); if (cinfo->output_components != 1) /* safety check: just one component? */ ERREXIT(cinfo, JERR_GIF_BUG); /* Create decompressor output buffer. */ dest->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1); dest->pub.buffer_height = 1; /* Allocate space for hash table */ dest->hash_code = (code_int *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, HSIZE * SIZEOF(code_int)); dest->hash_value = (hash_entry FAR *) (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, HSIZE * SIZEOF(hash_entry)); return (djpeg_dest_ptr) dest; } #endif /* GIF_SUPPORTED */ \ No newline at end of file diff --git a/Independent JPEG Group/wrppm.c b/Independent JPEG Group/wrppm.c new file mode 100644 index 0000000..827fa5c --- /dev/null +++ b/Independent JPEG Group/wrppm.c @@ -0,0 +1 @@ +/* * wrppm.c * * Copyright (C) 1991-1994, Thomas G. Lane. * This file is part of the Independent JPEG Group's software. * For conditions of distribution and use, see the accompanying README file. * * This file contains routines to write output images in PPM/PGM format. * The PBMPLUS library is NOT required to compile this software * (but it is highly useful as a set of PPM image manipulation programs). * * These routines may need modification for non-Unix environments or * specialized applications. As they stand, they assume output to * an ordinary stdio stream. */ #include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */ #ifdef PPM_SUPPORTED /* * Haven't yet got around to making this work with text-format output, * hence cannot handle pixels wider than 8 bits. */ #if BITS_IN_JSAMPLE != 8 Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */ #endif /* * In fact, it's worse than that: we want JSAMPLE to be a char, so that we * can just fwrite() the decompressed data to a raw-format PPM or PGM file. * * The output buffer needs to be writable by fwrite(). On PCs, we must * allocate the buffer in near data space, because we are assuming small-data * memory model, wherein fwrite() can't reach far memory. If you need to * process very wide images on a PC, you might have to compile in large-memory * model, or else replace fwrite() with a putc() loop --- which will be much * slower. */ /* Private version of data destination object */ typedef struct { struct djpeg_dest_struct pub; /* public fields */ JSAMPLE *iobuffer; /* non-FAR pointer to I/O buffer */ JSAMPROW pixrow; /* FAR pointer to same */ JDIMENSION buffer_width; /* width of one row */ } ppm_dest_struct; typedef ppm_dest_struct * ppm_dest_ptr; /* * Write some pixel data. * In this module rows_supplied will always be 1. */ METHODDEF void put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied) { ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); } /* * Write some pixel data when color quantization is in effect. * We have to demap the color index values to straight data. */ METHODDEF void put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied) { ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; register char * bufferptr; register int pixval; register JSAMPROW ptr; register JSAMPROW color_map0 = cinfo->colormap[0]; register JSAMPROW color_map1 = cinfo->colormap[1]; register JSAMPROW color_map2 = cinfo->colormap[2]; register JDIMENSION col; ptr = dest->pub.buffer[0]; bufferptr = (char *) dest->iobuffer; for (col = cinfo->output_width; col > 0; col--) { pixval = GETJSAMPLE(*ptr++); *bufferptr++ = (char) GETJSAMPLE(color_map0[pixval]); *bufferptr++ = (char) GETJSAMPLE(color_map1[pixval]); *bufferptr++ = (char) GETJSAMPLE(color_map2[pixval]); } (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); } METHODDEF void put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied) { ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; register char * bufferptr; register JSAMPROW ptr; register JSAMPROW color_map = cinfo->colormap[0]; register JDIMENSION col; ptr = dest->pub.buffer[0]; bufferptr = (char *) dest->iobuffer; for (col = cinfo->output_width; col > 0; col--) { *bufferptr++ = (char) GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)]); } (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); } /* * Startup: write the file header. */ METHODDEF void start_output (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) { ppm_dest_ptr dest = (ppm_dest_ptr) dinfo; /* Emit file header */ switch (cinfo->out_color_space) { case JCS_GRAYSCALE: /* emit header for raw PGM format */ fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n", (long) cinfo->output_width, (long) cinfo->output_height, 255); break; case JCS_RGB: /* emit header for raw PPM format */ fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n", (long) cinfo->output_width, (long) cinfo->output_height, 255); break; default: ERREXIT(cinfo, JERR_PPM_COLORSPACE); } } /* * Finish up at the end of the file. */ METHODDEF void finish_output (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo) { /* Make sure we wrote the output file OK */ fflush(dinfo->output_file); if (ferror(dinfo->output_file)) ERREXIT(cinfo, JERR_FILE_WRITE); } /* * The module selection routine for PPM format output. */ GLOBAL djpeg_dest_ptr jinit_write_ppm (j_decompress_ptr cinfo) { ppm_dest_ptr dest; /* This module does not work unless JSAMPLE is a char. */ /* Unfortunately, we can't test it at compile time. */ if (SIZEOF(JSAMPLE) != SIZEOF(char)) ERREXIT(cinfo, JERR_PPM_SAMPLESIZE); /* Create module interface object, fill in method pointers */ dest = (ppm_dest_ptr) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, SIZEOF(ppm_dest_struct)); dest->pub.start_output = start_output; dest->pub.finish_output = finish_output; /* Calculate output image dimensions so we can allocate space */ jpeg_calc_output_dimensions(cinfo); /* Create I/O buffer. Note we make this near on a PC. */ dest->buffer_width = cinfo->output_width * cinfo->out_color_components; dest->iobuffer = (JSAMPLE *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, (size_t) (dest->buffer_width * SIZEOF(JSAMPLE))); if (cinfo->quantize_colors) { /* When quantizing, need an output buffer for colormap indexes * that's separate from the physical I/O buffer. */ dest->pub.buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1); dest->pub.buffer_height = 1; if (cinfo->out_color_space == JCS_GRAYSCALE) dest->pub.put_pixel_rows = put_demapped_gray; else dest->pub.put_pixel_rows = put_demapped_rgb; } else { /* Normal case, will fwrite() directly from decompressor output buffer. */ /* Synthesize a JSAMPARRAY pointer structure */ /* Cast here implies near->far pointer conversion on PCs */ dest->pixrow = (JSAMPROW) dest->iobuffer; dest->pub.buffer = & dest->pixrow; dest->pub.buffer_height = 1; dest->pub.put_pixel_rows = put_pixel_rows; } return (djpeg_dest_ptr) dest; } #endif /* PPM_SUPPORTED */ \ No newline at end of file diff --git a/Infinity Windoid 2_6/Infinity Windoid.makeout b/Infinity Windoid 2_6/Infinity Windoid.makeout new file mode 100644 index 0000000..e005ddc --- /dev/null +++ b/Infinity Windoid 2_6/Infinity Windoid.makeout @@ -0,0 +1 @@ +Set Echo 1 \ No newline at end of file diff --git a/Infinity Windoid 2_6/InfinityWDEF.pef b/Infinity Windoid 2_6/InfinityWDEF.pef new file mode 100644 index 0000000000000000000000000000000000000000..e70c243a680c7bb5e7518a5c4164a1193bef3d61 GIT binary patch literal 11328 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

    +68NyPAU^Llp=dTk8&+F_tudN z{JW^?uUX9CMh)B%Lb)ehOT5CIpBRV3= z5YrDCC`B){y14Mf0|$u)^^j>_8Q-qQn*eo}ir?giEiQqBz(k_9yt~Sa=EVTOe0AKd zE1*mjm}pS$b~jgxf=>@!m5y9~nabDX5|b)0RUb#n##B|Pv;EyEl7|n!Vr8Ibs53cm zp!2|BXR4F30q#M)v(skWxp_<1=51Y@@xy<%iI0*l9m4rx#J&RKr7IHKgDGW_$!J!- zGy!PG9mUkgetP=7VfuAwy6ILz0eZL*xLqixy3ijFshI~G!N1(i20I7eTZoB^)#fF% z5jCv~x?;wrLM)+SCQUJ>C)e}nem?HL)X;=f4lRq+P(X9(q3CHci33Sftz_60M)s6H zq$5mF&y&vt`=D&BctQ%Jo~Ns4TUQ{Rkgy33z@w5_17f%a!5*V9s8YBYRI-Ze6fS82 zDWL=arr952>4i!^vPies^GwmFvVtPG(~iqRQ9^A)z}$B4~H=@xS#k& zJcO@#RSWwdr!bD?nccQ>=q6s#VxR~HoE&aw?qj435+PTeKrq9HfuS!T$5ik~4%k6F zqEW0h^JutQjuGY13Q-LK{`O%LT@gq~H4NSptjJzoNSWyw*u#C;Dg{)SkeG!|xV}ha z;=l~h$pk07D#ewnN?xUScqjZ0WS!}7&_bY=XMRGy3_-cP^?(PWM*K?GDZ~_T_ZV(w z7xpvJOEVb}B78LpV-|`PA!hW6J$Y1tj<>cMb(jpM=H`Oy{#Ot_rgC+lE_va~C~Ucd z!M(xOaElcK7A|Iy1*^lvtYS9eeo8D4j>L2Wd;~u}t2=3F(h037IR{CSuL_D=-6- z)l7AGZPD-7;Y$`tVt;m$RvZR(if9!`sDS$c)YCu_4Lq+JRiy`LR(dDV3HgGV=wgfE zhOEd$1!%OmvXH%So!~`%Mi{j|d2CiB=?elkU(t2j4W18Ex`I|^zQCvu)Wk^_HD^MSG@&}$2!p&f}&rg6`WghX@;hRi55h`0g7 zw(Fw#=^9YzPmPNkJSulmZxg7qDx=uCOF?U?U)QgEEb|l~GFC8@iEL zCsjcN^03NB8A)hUVU_p$qaffgeodztLUsi|){o||b;5nj*f$}T5;yPQ^$diy%{4H` zwyh}`!a|uJxCf=`eF;1UEsHY_>+7@BHoH3 zk*gFLG@f!?I9vep{SZ7|q1G}c>t$IWfVM&&F~cBHms~X(is3Aqd39H0hC4sVBy(_Z z2(dTlHAat78YM(hHx4k;@Q6m;u^%^iiEh2Y0Mnyo3LzE8ka>ts0Ow-3DAU;dl)5PX zscOjH5fvy(qSdvRqR>*$g$A6=A)CS7ASU6xyz)0Z(iWmS3sWi!vN7HrZp?U_fqKoP z0Jz070=|x`o=5zuDBp$Rx}y6cuqYUwMaj7=k=-o*N*+D%C)~!b9J7WFOMTs?9O% zh>j7YS?b1z;&oz@Mg%#i#MO0U*b<=xHFlA%k?qeiRb7q1>LI(^c_%c1F$IDJjav`` zoP%I19zb$>ra(;^bns&I;IVS%G8TobzYs~tu%LetQ<^uZaTPZ3kY_@UVt=r@*GccS5KFUu3)Ds|CRT zavw3;UJCD#`~yY>Q%ORUvYMf8M`+VGLtzMgpYJ__OhHq;R#+6UtIOE7216cStuj>P zQG=GvR!Tk6Y8d8cu)};hje!RfR6NN}8h8mlos027v1KS$050?rFh4QD>^{)Gq3q$j z<`D42i%+hUtw~pK-YdA-2OIx+r#)g0STF3C9z&ci))yh8v?U ztI5}N8Ln|4bg%L>4nJx_O-P=5ZX;W}G^&+s@>D6VxzKI)!R8G85;MG~`%NY6VAlr8 z;&eeutH%UVr$I;qnm8w6(IaIPT@os^uCRA2zzt(gXgAck;uL82!WW^=L~{`V9XJ8< zewb89g{%#QH*T_y$iVwhQbKr?S^SC?TS3d_c{h*qG&_Px# literal 0 HcmV?d00001 diff --git a/JFIF Preview/JFIFPreview.c b/JFIF Preview/JFIFPreview.c new file mode 100644 index 0000000..56ee17b --- /dev/null +++ b/JFIF Preview/JFIFPreview.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #define SystemSevenOrLater 1 #include #include #include #include #include #include #include #include /* * Macros and typedefs * */ #define JFIFPreviewVersion 0x00010001 #define kBufferSize 20 #define Height(r) ((r)->bottom - (r)->top) #define Width(r) ((r)->right - (r)->left) #define pnotDisplayPreview 1 typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned long ulong; enum { uppPreviewOpenProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentInstance))), uppPreviewCloseProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(ComponentInstance))), uppPreviewCanDoProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(short))), uppPreviewDisplayProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(OSType))) | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(Handle))) | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(const Rect *))) }; /* * Function prototypes * */ extern pascal ComponentResult EntryPoint(ComponentParameters *params, Handle storage); pascal ComponentResult JFIFPreviewOpen(ComponentInstance self); pascal ComponentResult JFIFPreviewClose(Handle theBuffer, ComponentInstance self); pascal ComponentResult JFIFPreviewCanDo(short selector); pascal ComponentResult JFIFPreviewShow(Handle theBuffer, OSType dataType, Handle data, const Rect *inHere); OSErr LoadPreview(Handle *theData, short theFile, uchar *buffer, short width, short height); OSErr LoadPreviewExtension(Handle *theData, short theFile, long theSize); OSErr MakePreviewGWorld(GWorldPtr *theGWorld, const Rect *inHere, short width, short height); OSErr DrawPreview(Handle previewData, const Rect *inHere, short width, short height); uchar *ParseJPEG(uchar *theAdr, long theLen, uchar theCode); OSErr MakeImageDescription(ImageDescriptionHandle *theDesc, Handle previewData); OSErr DrawJPEGPreview(Handle previewData, const Rect *inHere); OSErr Draw1CompPreview(Handle previewData, const Rect *inHere); OSErr Draw3CompPreview(Handle previewData, const Rect *inHere); #if defined(powerc) || defined(__powerc) enum { uppMainProcInfo = kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(ComponentResult))) | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(ComponentParameters *))) | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(Handle))) }; RoutineDescriptor EntryPointRD = BUILD_ROUTINE_DESCRIPTOR(uppMainProcInfo, EntryPoint); #endif /* * This is the entry point where we dispatch the request to the appropriate function * */ extern pascal ComponentResult EntryPoint(ComponentParameters *params, Handle storage) { ComponentFunctionUPP theRoutine = nil; ComponentResult theResult = noErr; switch (params->what) { case kComponentOpenSelect: if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewOpen, uppPreviewOpenProcInfo, GetCurrentISA())) theResult = CallComponentFunction(params, theRoutine); break; case kComponentCloseSelect: if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewClose, uppPreviewCloseProcInfo, GetCurrentISA())) theResult = CallComponentFunctionWithStorage(storage, params, theRoutine); break; case kComponentCanDoSelect: if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewCanDo, uppPreviewCanDoProcInfo, GetCurrentISA())) theResult = CallComponentFunction(params, theRoutine); break; case kComponentVersionSelect: return JFIFPreviewVersion; case pnotDisplayPreview: if (theRoutine = NewRoutineDescriptor((ProcPtr)JFIFPreviewShow, uppPreviewDisplayProcInfo, GetCurrentISA())) theResult = CallComponentFunctionWithStorage(storage, params, theRoutine); break; default: theResult = badComponentSelector; break; } if (theRoutine) DisposeRoutineDescriptor(theRoutine); return theResult; } /* * Open Component function: Allocate our global storage * */ pascal ComponentResult JFIFPreviewOpen(ComponentInstance self) { Handle theBuffer; if (!(theBuffer = NewHandle(kBufferSize))) return MemError(); SetComponentInstanceStorage(self, theBuffer); return noErr; } /* * Close Component function: Dispose of our global storage * */ pascal ComponentResult JFIFPreviewClose(Handle theBuffer, ComponentInstance self) { #if applec #pragma unused(self) #endif if (theBuffer) DisposeHandle(theBuffer); return noErr; } /* * Can Do function: return 1 for any selector we can handle * */ pascal ComponentResult JFIFPreviewCanDo(short selector) { switch (selector) { case kComponentOpenSelect: case kComponentCloseSelect: case kComponentCanDoSelect: case kComponentVersionSelect: case pnotDisplayPreview: return 1; default: return 0; } } /* * Show preview function: accept an alias and extract a preview from it * * INTERESTING FACT: * * If we return an error, QuickTime will go ahead and use any custom icon as the preview, * so we return an error if there is no JFIF preview, in order to preserve this * functionality * */ pascal ComponentResult JFIFPreviewShow(Handle theBuffer, OSType dataType, Handle data, const Rect *inHere) { long theLength = kBufferSize; short fileRef, width, height; Handle previewData; Boolean isFolder; FSSpec theFile; OSErr theErr; uchar *buf; if (dataType != rAliasType) return paramErr; HLock(theBuffer); buf = (uchar *)*theBuffer; theErr = ResolveAlias(nil, (AliasHandle)data, &theFile, &isFolder); if (theErr == noErr) { theErr = FSpOpenDF(&theFile, fsRdPerm, &fileRef); if (theErr == noErr) { theErr = FSRead(fileRef, &theLength, buf); if (theErr == noErr && buf[0] == 0xff && buf[1] == 0xd8 && buf[2] == 0xff && buf[3] == 0xe0 && buf[6] == 'J' && buf[7] == 'F' && buf[8] == 'I' && buf[9] == 'F' && buf[10] == 0) { width = buf[18]; height = buf[19]; if (width && height) { theErr = LoadPreview(&previewData, fileRef, buf, width, height); if (theErr == noErr) { theErr = DrawPreview(previewData, inHere, width, height); DisposeHandle(previewData); } } else { SetFPos(fileRef, fsFromStart, 4 + (buf[4] << 8) + buf[5]); theLength = 10; theErr = FSRead(fileRef, &theLength, buf); if (theErr == noErr && buf[0] == 0xff && buf[1] == 0xe0 && buf[4] == 'J' && buf[5] == 'F' && buf[6] == 'X' && buf[7] == 'X' && buf[8] == 0) { theErr = LoadPreviewExtension(&previewData, fileRef, (buf[2] << 8) + buf[3] - 8); if (theErr == noErr) { switch (buf[9]) { case 0x10: theErr = DrawJPEGPreview(previewData, inHere); break; case 0x11: theErr = Draw1CompPreview(previewData, inHere); break; case 0x13: theErr = Draw3CompPreview(previewData, inHere); break; } DisposeHandle(previewData); } } else theErr = memFullErr; // fake an error if no preview around } } FSClose(fileRef); } } HUnlock(theBuffer); return theErr; } /* * LoadPreview: Allocate a new handle and read the preview data into it * */ OSErr LoadPreview(Handle *theData, short theFile, uchar *buffer, short width, short height) { #if applec #pragma unused(buffer) #endif long theSize = (long)width * (long)height * 3L; OSErr theErr = noErr; if (!(*theData = NewHandle(theSize))) { *theData = TempNewHandle(theSize, &theErr); if (theErr != noErr) return theErr; } HLock(*theData); theErr = FSRead(theFile, &theSize, **theData); HUnlock(*theData); return theErr; } /* * LoadPreviewExtension: Allocate a new handle and read the preview extension data into it * */ OSErr LoadPreviewExtension(Handle *theData, short theFile, long theSize) { OSErr theErr = noErr; if (!(*theData = NewHandle(theSize))) { *theData = TempNewHandle(theSize, &theErr); if (theErr != noErr) return theErr; } HLock(*theData); theErr = FSRead(theFile, &theSize, **theData); HUnlock(*theData); return theErr; } /* * MakePreviewGWorld: Create a GWorld the proper size for the given preview width and * height * */ OSErr MakePreviewGWorld(GWorldPtr *theGWorld, const Rect *inHere, short width, short height) { Rect GWBounds; OSErr theErr; GWBounds.left = GWBounds.top = 0; GWBounds.bottom = (height > Height(inHere)) ? Height(inHere) : height; GWBounds.right = (width > Width(inHere)) ? Width(inHere) : width; theErr = NewGWorld(theGWorld, 32, &GWBounds, nil, nil, 0); if (theErr != noErr) theErr = NewGWorld(theGWorld, 32, &GWBounds, nil, nil, useTempMem); return theErr; } /* * DrawPreview: Make a GWorld and copy the preview data into it; then do a CopyBits into * the requested area * */ OSErr DrawPreview(Handle previewData, const Rect *inHere, short width, short height) { PixMapHandle thePixMap, dstPixMap; uchar *bufPtr, *pixPtr, *pixBase; Rect GWBounds, dstRect = *inHere; short rowBytes, r, c, oldWidth; GWorldPtr theGWorld, curGWorld; char mmuMode = true32b; OSErr theErr = noErr; GDHandle curDevice; if (!(oldWidth = width)) { width = *(uchar *)*previewData; height = *((uchar *)*previewData + 1); } theErr = MakePreviewGWorld(&theGWorld, inHere, width, height); if (theErr == noErr) { GWBounds = theGWorld->portRect; LockPixels(thePixMap = GetGWorldPixMap(theGWorld)); pixBase = (uchar *)GetPixBaseAddr(thePixMap); rowBytes = (*thePixMap)->rowBytes & 0x3fff; bufPtr = (uchar *)StripAddress(*previewData); if (!oldWidth) bufPtr++; SwapMMUMode(&mmuMode); for (r = 0; r < GWBounds.bottom; r++) { pixPtr = pixBase; for (c = 0; c < GWBounds.right; c++) { pixPtr++; *pixPtr++ = *bufPtr++; *pixPtr++ = *bufPtr++; *pixPtr++ = *bufPtr++; } bufPtr += 3L * (long)(width - GWBounds.right); pixBase += rowBytes; } SwapMMUMode(&mmuMode); dstRect.left += (Width(inHere) - GWBounds.right) >> 1; dstRect.top += (Height(inHere) - GWBounds.bottom) >> 1; dstRect.right = dstRect.left + GWBounds.right; dstRect.bottom = dstRect.top + GWBounds.bottom; GetGWorld(&curGWorld, &curDevice); dstPixMap = GetGWorldPixMap(curGWorld); CopyBits((BitMap *)*thePixMap, (BitMap *)*dstPixMap, &GWBounds, &dstRect, srcCopy + ditherCopy, nil); DisposeGWorld(theGWorld); } return theErr; } /* * ParseJPEG: returns a pointer to the first instance of the specified code in the * given JPEG stream * */ uchar *ParseJPEG(uchar *theAdr, long theLen, uchar theCode) { uchar *theEnd = theAdr + theLen; long theSize; while (true) { while ((*theAdr++ != 0xff) && (theAdr < theEnd)); if (theAdr >= theEnd) return nil; while (*theAdr == 0xff) theAdr++; if (theAdr >= theEnd) return nil; if (*theAdr == theCode) break; else if (*theAdr == 0xd9) return nil; else if ((*theAdr <= 0x01) || ((*theAdr >= 0xd0) && (*theAdr <= 0xd8))) { theAdr++; continue; } theAdr++; if ((theSize = (*theAdr << 8) + *(theAdr + 1)) < 0) return nil; if ((theAdr + theSize) >= theEnd) { *(theAdr - 1) = 0xd9; return nil; } else theAdr += theSize; } theAdr += 3; return theAdr; } /* * MakeImageDescription: create an image description record for the given JPEG image * */ OSErr MakeImageDescription(ImageDescriptionHandle *theDesc, Handle previewData) { long theLen = GetHandleSize(previewData); CodecInfo theInfo; uchar *theData; short theCode; OSErr theErr; theErr = GetCodecInfo(&theInfo, 'jpeg', 0); if (theErr == noErr) { *theDesc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription)); if (!*theDesc) { *theDesc = (ImageDescriptionHandle)TempNewHandle(sizeof(ImageDescription), &theErr); if (theErr != noErr) return theErr; } for (theCode = 0xc0; theCode < 0xd0; theCode++) if (theData = ParseJPEG((uchar *)*previewData, theLen, theCode)) break; if (theCode != 0xd0) { (**theDesc)->idSize = sizeof(ImageDescription); (**theDesc)->cType = 'jpeg'; (**theDesc)->resvd1 = (**theDesc)->resvd2 = (**theDesc)->dataRefIndex = 0; BlockMove(theInfo.typeName, (**theDesc)->name, 32); (**theDesc)->version = theInfo.version; (**theDesc)->revisionLevel = theInfo.revisionLevel; (**theDesc)->vendor = theInfo.vendor; (**theDesc)->temporalQuality = 0; (**theDesc)->spatialQuality = 0x200L; (**theDesc)->width = (theData[3] << 8) + theData[4]; (**theDesc)->height = (theData[1] << 8) + theData[2]; (**theDesc)->hRes = (**theDesc)->vRes = 0x480000L; (**theDesc)->dataSize = theLen; (**theDesc)->frameCount = 1; (**theDesc)->depth = 32; (**theDesc)->clutID = -1; } else theErr = memFullErr; } return theErr; } /* * DrawJPEGPreview: draws a preview image in JPEG format * */ OSErr DrawJPEGPreview(Handle previewData, const Rect *inHere) { Rect srcRect, dstRect = *inHere; ImageDescriptionHandle theDesc; PixMapHandle thePixMap; MatrixRecord theMatrix; OSErr theErr = noErr; GWorldPtr curGWorld; short width, height; GDHandle curDevice; theErr = MakeImageDescription(&theDesc, previewData); if (theErr == noErr) { width = (*theDesc)->width; height = (*theDesc)->height; srcRect.left = srcRect.top = 0; srcRect.bottom = (height > Height(inHere)) ? Height(inHere) : height; srcRect.right = (width > Width(inHere)) ? Width(inHere) : width; dstRect.left += (Width(inHere) - srcRect.right) >> 1; dstRect.top += (Height(inHere) - srcRect.bottom) >> 1; dstRect.right = dstRect.left + srcRect.right; dstRect.bottom = dstRect.top + srcRect.bottom; GetGWorld(&curGWorld, &curDevice); thePixMap = GetGWorldPixMap(curGWorld); RectMatrix(&theMatrix, &srcRect, &dstRect); HLock(previewData); theErr = FDecompressImage(StripAddress(*previewData), theDesc, thePixMap, &srcRect, &theMatrix, srcCopy + ditherCopy, nil, nil, nil, codecHighQuality, anyCodec, GetHandleSize(previewData), nil, nil); HUnlock(previewData); DisposeHandle((Handle)theDesc); } return theErr; } /* * Draw1CompPreview: draws a preview image 256-color palette format * */ OSErr Draw1CompPreview(Handle previewData, const Rect *inHere) { short rowBytes, r, c, width, height; ulong *pixPtr, *pixBase, *theColor; PixMapHandle thePixMap, dstPixMap; Rect GWBounds, dstRect = *inHere; GWorldPtr theGWorld, curGWorld; uchar *bufPtr, *colPtr; char mmuMode = true32b; OSErr theErr = noErr; Handle colorsHandle; GDHandle curDevice; colorsHandle = NewHandle(256 * sizeof(long)); if (!colorsHandle) { colorsHandle = TempNewHandle(256 * sizeof(long), &theErr); if (theErr != noErr) return theErr; } width = *(uchar *)*previewData; height = *((uchar *)*previewData + 1); theErr = MakePreviewGWorld(&theGWorld, inHere, width, height); if (theErr == noErr) { GWBounds = theGWorld->portRect; LockPixels(thePixMap = GetGWorldPixMap(theGWorld)); pixBase = (ulong *)GetPixBaseAddr(thePixMap); rowBytes = (*thePixMap)->rowBytes & 0x3fff; bufPtr = (uchar *)StripAddress(*previewData) + 2; theColor = (ulong *)(colPtr = (uchar *)StripAddress(*colorsHandle)); for (c = 0; c < 256; c++) { *colPtr++ = 0; *colPtr++ = *bufPtr++; *colPtr++ = *bufPtr++; *colPtr++ = *bufPtr++; } SwapMMUMode(&mmuMode); for (r = 0; r < GWBounds.bottom; r++) { pixPtr = pixBase; for (c = 0; c < GWBounds.right; c++) *pixPtr++ = theColor[*bufPtr++]; bufPtr += 3L * (long)(width - GWBounds.right); pixBase += rowBytes >> 2; } SwapMMUMode(&mmuMode); dstRect.left += (Width(inHere) - GWBounds.right) >> 1; dstRect.top += (Height(inHere) - GWBounds.bottom) >> 1; dstRect.right = dstRect.left + GWBounds.right; dstRect.bottom = dstRect.top + GWBounds.bottom; GetGWorld(&curGWorld, &curDevice); dstPixMap = GetGWorldPixMap(curGWorld); CopyBits((BitMap *)*thePixMap, (BitMap *)*dstPixMap, &GWBounds, &dstRect, srcCopy + ditherCopy, nil); DisposeGWorld(theGWorld); } return theErr; } /* * Draw3CompPreview: draws a preview image 24-bit color format * */ OSErr Draw3CompPreview(Handle previewData, const Rect *inHere) { return DrawPreview(previewData, inHere, 0, 0); } \ No newline at end of file diff --git a/JFIF Preview/JFIFPreview.fat.r b/JFIF Preview/JFIFPreview.fat.r new file mode 100644 index 0000000..1398a1b --- /dev/null +++ b/JFIF Preview/JFIFPreview.fat.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // ***************************************************************************** // // JFIFPreview.fat.r -- Rez code to support building a Fat or PPC-only version // // ***************************************************************************** #include "MixedMode.r" // ----------------------------------------------------------------------------- #ifdef POWER_PC_ONLY type 'pnot' as 'rdes'; resource 'pnot' (4213) { 0x000003F0, // PowerPC ProcInfo $$Resource("JFIFPreview.rsrc", 'pCod', 4213) // Specify name, type, and ID of resource // containing a pef container }; // ----------------------------------------------------------------------------- #else type 'pnot' as 'sdes'; resource 'pnot' (4213) { 0x000003F0, // 68K ProcInfo 0x000003F0, // PowerPC ProcInfo $$Resource("JFIFPreview.rsrc", 'oCod', 4213), // name, type, and ID of rsrc containing 68k code $$Resource("JFIFPreview.rsrc", 'pCod', 4213) // name, type, and ID of rsrc containing ppc code }; // ----------------------------------------------------------------------------- #endif \ No newline at end of file diff --git a/JFIF Preview/JFIFPreview.r b/JFIF Preview/JFIFPreview.r new file mode 100644 index 0000000..9c0dd82 --- /dev/null +++ b/JFIF Preview/JFIFPreview.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #define UseExtendedThingResource 1 #include "Types.r" #include "SysTypes.r" //#include "ImageCodec.r" #define pnotComponentNeedsNoCache 2 #define kVersion 0x102 #define kJPEGViewVersion 0x330 #define displayPreviewComponent 'pnot' #define kJPEGType 'JPEG' #define kJFIFType 'JFIF' #define kManufacturer 'ASGD' #define rthngResource 4213 #define rthngResource2 4214 #define rNameResource 4213 #define rInfoResource 4214 #define r68kCode 4213 #define rPPCCode 4214 include "JFIFPreview.68k"; read displayPreviewComponent (4214) "JFIFPreview.ppc"; include "JFIFPreview.suppl.rsrc"; resource 'vers' (1) { (kVersion >> 8), kVersion & 0xff, final, 0x00, verUS, "1.0.2", "1.0.2 ©1992Ð94, Aaron Giles\n" "All Rights Reserved" }; resource 'vers' (2) { (kJPEGViewVersion >> 8), kJPEGViewVersion & 0xff, final, 0x00, verUS, "3.3", "distributed with JPEGView 3.3" }; resource 'thng' (rthngResource) { displayPreviewComponent, kJPEGType, kManufacturer, pnotComponentNeedsNoCache, 0, displayPreviewComponent, rthngResource, 'STR ', rNameResource, 'STR ', rInfoResource, 0, 0, 0x00010001, componentHasMultiplePlatforms, 128, { cmpWantsRegisterMessage, displayPreviewComponent, r68kCode, platform68k, cmpWantsRegisterMessage, displayPreviewComponent, rPPCCode, platformPowerPC } }; resource 'thng' (rthngResource2) { displayPreviewComponent, kJFIFType, kManufacturer, pnotComponentNeedsNoCache, 0, displayPreviewComponent, rthngResource, 'STR ', rNameResource, 'STR ', rInfoResource, 0, 0, 0x00010001, componentHasMultiplePlatforms, 128, { pnotComponentNeedsNoCache, displayPreviewComponent, r68kCode, platform68k, pnotComponentNeedsNoCache, displayPreviewComponent, rPPCCode, platformPowerPC } }; resource 'STR ' (rNameResource) { "JPEGView JFIF Preview Component"; }; resource 'STR ' (rInfoResource) { "Displays and extracts JFIF preview images (through version 1.01 of the JFIF spec)"; }; \ No newline at end of file diff --git a/JFIF Preview/Makefile.TXT b/JFIF Preview/Makefile.TXT new file mode 100644 index 0000000..1779671 --- /dev/null +++ b/JFIF Preview/Makefile.TXT @@ -0,0 +1 @@ +#********************************************************* #* This source code copyright (c) 1991-2001, Aaron Giles * #* See the Read Me file for licensing information. * #* Contact email: mac@aarongiles.com * #********************************************************* Output = JPEGView JFIF Preview Type = thng Creator = JVJP ResType = pnot ResID68k = 4213 ResIDPPC = 4214 PPCPefLibs = -l InterfaceLib.xcoff=InterfaceLib ¶ -l StdCLib.xcoff=StdCLib ¶ -l QuickTimeLib.xcoff=QuickTimeLib ¶ -l MathLib.xcoff=MathLib PPCLinkLibs = "{PPCLibraries}"InterfaceLib.xcoff ¶ "{PPCLibraries}"StdCLib.xcoff ¶ "{PPCLibraries}"QuickTimeLib.xcoff ¶ "{PPCLibraries}"StdCRuntime.o ¶ "{PPCLibraries}"PPCCRuntime.o "JPEGView JFIF Preview" Ä JFIFPreview.ppc JFIFPreview.68k JFIFPreview.r Rez JFIFPreview.r -o "JPEGView JFIF Preview" SetFile "JPEGView JFIF Preview" -a B JFIFPreview.c.o.68k Ä JFIFPreview.c C -b -mbg off -opt full -i "{PPCCIncludes}" JFIFPreview.c -o JFIFPreview.c.o.68k JFIFPreview.68k Ä JFIFPreview.c.o.68k Link JFIFPreview.c.o.68k ¶ "{Libraries}"Interface.o ¶ -t rsrc ¶ -c RSED ¶ -rt pnot=4213 ¶ -m ENTRYPOINT ¶ -sg "JPEGView JFIF Preview" ¶ -o JFIFPreview.68k JFIFPreview.c.o.ppc Ä JFIFPreview.c PPCC -appleext on -opt speed JFIFPreview.c -o JFIFPreview.c.o.ppc JFIFPreview.ppc Ä JFIFPreview.c.o.ppc PPCLink JFIFPreview.c.o.ppc ¶ {PPCLinkLibs} ¶ -main EntryPointRD ¶ -o JFIFPreview.xcoff MakePEF -b JFIFPreview.xcoff -o JFIFPreview.ppc {PPCPefLibs} \ No newline at end of file diff --git a/JFIF Preview/obj/InfinityWDEF.xcoff b/JFIF Preview/obj/InfinityWDEF.xcoff new file mode 100644 index 0000000000000000000000000000000000000000..1c40817685c8eac911bb30572b35a9e089d7e1b0 GIT binary patch literal 59593 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 literal 0 HcmV?d00001 diff --git a/JFIF Preview/obj/JFIFPreview.c.o b/JFIF Preview/obj/JFIFPreview.c.o new file mode 100644 index 0000000000000000000000000000000000000000..51fd694766f35347912186ef320f73ac4d6ff052 GIT binary patch literal 4048 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 AqyPW_ literal 0 HcmV?d00001 diff --git a/JFIF Preview/obj/JFIFPreview.o b/JFIF Preview/obj/JFIFPreview.o new file mode 100644 index 0000000000000000000000000000000000000000..49852471896ab9f84517be9ef5963f018b9b6e19 GIT binary patch literal 10795 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 BlBNIv literal 0 HcmV?d00001 diff --git a/JPEGView 3 3 docs.pdf b/JPEGView 3 3 docs.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6de333e2ced4c7abe3ce168013059aae17061473 GIT binary patch literal 623286 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

    Th_3ttxA>u%xX}9@m6vCDh3*Kjg|cYcs=WRz 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 K)5Ez5N}^~2S0FFX)c7M3U!UN~jM{ER7 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

    +;YaAzMd^_tr;?Juk@Xf6+m9j|Qk&4a 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%0DK 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�{E3^9(p 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�VAsdkD(E-fmFg-$(o- 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 C6UCwc literal 0 HcmV?d00001 diff --git a/JPEGView 3_3 Æ’/JPEGView b/JPEGView 3_3 Æ’/JPEGView new file mode 100644 index 0000000000000000000000000000000000000000..ec1aaeddfaac714c26321b3e2fadc0f98fa660dd GIT binary patch literal 360560 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 DGVco@ literal 0 HcmV?d00001 diff --git a/Libraries/JPEGLib.xcoff b/Libraries/JPEGLib.xcoff new file mode 100644 index 0000000000000000000000000000000000000000..62142bcbf37c12caf4872cfa8e980ccd228eb859 GIT binary patch literal 135538 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 literal 0 HcmV?d00001 diff --git a/Make Resources.TXT b/Make Resources.TXT new file mode 100644 index 0000000..caab4a7 --- /dev/null +++ b/Make Resources.TXT @@ -0,0 +1 @@ +directory Development:Projects:JPEGView:JPEGView buildprogram resources \ No newline at end of file diff --git a/Makefile.TXT b/Makefile.TXT new file mode 100644 index 0000000..3d8a346 --- /dev/null +++ b/Makefile.TXT @@ -0,0 +1 @@ +#********************************************************* #* This source code copyright (c) 1991-2001, Aaron Giles * #* See the Read Me file for licensing information. * #* Contact email: mac@aarongiles.com * #********************************************************* #-------------------------------------------------------------------- # # JPEGView MakeFile # # Created: 23 Jan 94 # Modified: 17 Mar 94 # #-------------------------------------------------------------------- # Step 1: Define the variables #-------------------------------------------------------------------- #--------------------------------- General application variables AppName = JPEGView Creator = 'JVWR' Type = 'APPL' #--------------------------------- Directories and dependencies ObjDir = :Objects: CSrcDir = :Source:C: 68kSrcDir = :Source:68020: RsrcDir = :Resources: HeaderDir = :Headers: LinkDir = :LinkerOutput: IWDir = :InfinityWindoid: "{ObjDir}" Ä "{CSrcDir}" "{68kSrcDir}" #--------------------------------- Include paths IncludePaths = -i "{MPW}"Interfaces:PPCCIncludes: -i "{HeaderDir}" -i : #--------------------------------- Library variables PPCLibs = "{PPCLibraries}"DragLib.xcoff ¶ "{PPCLibraries}"InterfaceLib.xcoff ¶ "{PPCLibraries}"PPCCRuntime.o ¶ "{PPCLibraries}"StdCLib.xcoff ¶ "{PPCLibraries}"StdCRuntime.o ¶ "{PPCLibraries}"QuickTimeLib.xcoff ¶ "{PPCLibraries}"ObjectSupportLib.xcoff ¶ :Libraries:JPEGLib.xcoff PPCRuntime = -l DragLib.xcoff=DragLib~ ¶ -l InterfaceLib.xcoff=InterfaceLib ¶ -l StdCLib.xcoff=StdCLib ¶ -l QuickTimeLib.xcoff=QuickTimeLib~ ¶ -l ObjectSupportLib.xcoff=ObjectSupportLib~ PPCSoftLinks = 68kLibs = "{CLibraries}"StdCLib.o ¶ "{Libraries}"Runtime.o ¶ "{Libraries}"Interface.o ¶ "{Libraries}"AEObjectSupportLib.o ¶ :Libraries:JPEGLib.o #--------------------------------- Object list variables PPCObjects = "{ObjDir}"AppleEventUtils.c.ppc.o ¶ "{ObjDir}"AppleMenu.c.ppc.o ¶ "{ObjDir}"BMP.c.ppc.o ¶ "{ObjDir}"Bottlenecks.c.ppc.o ¶ "{ObjDir}"cApplication.c.ppc.o ¶ "{ObjDir}"cDocument.c.ppc.o ¶ "{ObjDir}"cDrawingArea.c.ppc.o ¶ "{ObjDir}"cFile.c.ppc.o ¶ "{ObjDir}"cImage.c.ppc.o ¶ "{ObjDir}"ColorsMenu.c.ppc.o ¶ "{ObjDir}"ColorsWindow.c.ppc.o ¶ "{ObjDir}"CommentsWindow.c.ppc.o ¶ "{ObjDir}"CompressedResource.c.ppc.o ¶ "{ObjDir}"CoreEventHandlers.c.ppc.o ¶ "{ObjDir}"cPixelMap.c.ppc.o ¶ "{ObjDir}"cSelection.c.ppc.o ¶ "{ObjDir}"CustomCopyBits.c.ppc.o ¶ "{ObjDir}"cWindow.c.ppc.o ¶ "{ObjDir}"DialogUtils.c.ppc.o ¶ "{ObjDir}"EditMenu.c.ppc.o ¶ "{ObjDir}"EventHandlers.c.ppc.o ¶ "{ObjDir}"EventUtils.c.ppc.o ¶ "{ObjDir}"FileMenu.c.ppc.o ¶ "{ObjDir}"FloatingWindows.c.ppc.o ¶ "{ObjDir}"GeneralMenus.c.ppc.o ¶ "{ObjDir}"GIF.c.ppc.o ¶ "{ObjDir}"HelpMenu.c.ppc.o ¶ "{ObjDir}"ImageUtils.c.ppc.o ¶ "{ObjDir}"JPEG.c.ppc.o ¶ "{ObjDir}"JPEGNoQuickTime.c.ppc.o ¶ "{ObjDir}"JPEGView.c.ppc.o ¶ "{ObjDir}"JPEGViewEventHandlers.c.ppc.o ¶ "{ObjDir}"JPEGViewGlobals.c.ppc.o ¶ "{ObjDir}"MarchingAnts.c.ppc.o ¶ "{ObjDir}"MemoryUtils.c.ppc.o ¶ "{ObjDir}"MercutioAPI.c.ppc.o ¶ "{ObjDir}"MiscellaneousUtils.c.ppc.o ¶ "{ObjDir}"MonitorUtils.c.ppc.o ¶ "{ObjDir}"PICT.c.ppc.o ¶ "{ObjDir}"PNTG.c.ppc.o ¶ "{ObjDir}"Preferences.c.ppc.o ¶ "{ObjDir}"ProgressProcs.c.ppc.o ¶ "{ObjDir}"QDxDispatchPatch.c.ppc.o ¶ "{ObjDir}"Quantize.c.ppc.o ¶ "{ObjDir}"QuickDrawUtils.c.ppc.o ¶ "{ObjDir}"RequiredEventHandlers.c.ppc.o ¶ "{ObjDir}"SaveOpen.c.ppc.o ¶ "{ObjDir}"SCRN.c.ppc.o ¶ "{ObjDir}"SendAppleEvents.c.ppc.o ¶ "{ObjDir}"SlideControlsWindow.c.ppc.o ¶ "{ObjDir}"SlideShow.c.ppc.o ¶ "{ObjDir}"SlideShowOptions.c.ppc.o ¶ "{ObjDir}"StandardFolder.c.ppc.o ¶ "{ObjDir}"StatisticsWindow.c.ppc.o ¶ "{ObjDir}"TIFF.c.ppc.o ¶ "{ObjDir}"ViewMenu.c.ppc.o ¶ "{ObjDir}"WindowMenu.c.ppc.o ¶ "{ObjDir}"WindowUtils.c.ppc.o 68kObjects = "{ObjDir}"AppleEventUtils.c.68k.o ¶ "{ObjDir}"AppleMenu.c.68k.o ¶ "{ObjDir}"BMP.c.68k.o ¶ "{ObjDir}"Bottlenecks.c.68k.o ¶ "{ObjDir}"cApplication.c.68k.o ¶ "{ObjDir}"cDocument.c.68k.o ¶ "{ObjDir}"cDrawingArea.c.68k.o ¶ "{ObjDir}"cFile.c.68k.o ¶ "{ObjDir}"cImage.c.68k.o ¶ "{ObjDir}"ColorsMenu.c.68k.o ¶ "{ObjDir}"ColorsWindow.c.68k.o ¶ "{ObjDir}"CommentsWindow.c.68k.o ¶ "{ObjDir}"CompressedResource.c.68k.o ¶ "{ObjDir}"CoreEventHandlers.c.68k.o ¶ "{ObjDir}"cPixelMap.c.68k.o ¶ "{ObjDir}"cSelection.c.68k.o ¶ "{ObjDir}"CustomCopyBits.c.68k.o ¶ "{ObjDir}"CustomCopyBits.a.68k.o ¶ "{ObjDir}"cWindow.c.68k.o ¶ "{ObjDir}"DialogUtils.c.68k.o ¶ "{ObjDir}"EditMenu.c.68k.o ¶ "{ObjDir}"EventHandlers.c.68k.o ¶ "{ObjDir}"EventUtils.c.68k.o ¶ "{ObjDir}"FileMenu.c.68k.o ¶ "{ObjDir}"FloatingWindows.c.68k.o ¶ "{ObjDir}"GeneralMenus.c.68k.o ¶ "{ObjDir}"GIF.a.68k.o ¶ "{ObjDir}"GIF.c.68k.o ¶ "{ObjDir}"HelpMenu.c.68k.o ¶ "{ObjDir}"ImageUtils.c.68k.o ¶ "{ObjDir}"JPEG.c.68k.o ¶ "{ObjDir}"JPEGNoQuickTime.c.68k.o ¶ "{ObjDir}"JPEGView.c.68k.o ¶ "{ObjDir}"JPEGViewEventHandlers.c.68k.o ¶ "{ObjDir}"JPEGViewGlobals.c.68k.o ¶ "{ObjDir}"MarchingAnts.c.68k.o ¶ "{ObjDir}"MemoryUtils.c.68k.o ¶ "{ObjDir}"MercutioAPI.c.68k.o ¶ "{ObjDir}"MiscellaneousUtils.c.68k.o ¶ "{ObjDir}"MonitorUtils.c.68k.o ¶ "{ObjDir}"PICT.c.68k.o ¶ "{ObjDir}"PNTG.c.68k.o ¶ "{ObjDir}"Preferences.c.68k.o ¶ "{ObjDir}"ProgressProcs.c.68k.o ¶ "{ObjDir}"QDxDispatchPatch.c.68k.o ¶ "{ObjDir}"Quantize.a.68k.o ¶ "{ObjDir}"Quantize.c.68k.o ¶ "{ObjDir}"QuickDrawUtils.c.68k.o ¶ "{ObjDir}"RequiredEventHandlers.c.68k.o ¶ "{ObjDir}"SaveOpen.c.68k.o ¶ "{ObjDir}"SCRN.c.68k.o ¶ "{ObjDir}"SendAppleEvents.c.68k.o ¶ "{ObjDir}"SlideControlsWindow.c.68k.o ¶ "{ObjDir}"SlideShow.c.68k.o ¶ "{ObjDir}"SlideShowOptions.c.68k.o ¶ "{ObjDir}"StandardFolder.c.68k.o ¶ "{ObjDir}"StatisticsWindow.c.68k.o ¶ "{ObjDir}"TIFF.c.68k.o ¶ "{ObjDir}"ViewMenu.c.68k.o ¶ "{ObjDir}"WindowMenu.c.68k.o ¶ "{ObjDir}"WindowUtils.c.68k.o #--------------------------------- Compiler options PPCCOptions = -sym off -appleext on {IncludePaths} PPCCOptionsOpt = -opt speed -appleext on {IncludePaths} 68kCOptions = -mbg off -sym off -r -mc68020 -opt speed {IncludePaths} 68kAsmOptions = -case object -i "{68kSrcDir}" #-------------------------------------------------------------------- # Step 2: Dependencies for the fat binary #-------------------------------------------------------------------- #--------------------------------- The application itself {AppName}.fat ÄÄ {AppName}.ppc {AppName}.68k "{AppName} Help" duplicate -d -y {AppName}.ppc {AppName}.fat SetFile {AppName}.fat -a BM echo "include ¶"{AppName}.68k¶" 'CODE';" | Rez -o {AppName}.fat -append #--------------------------------- Resources for the application {AppName}.fat ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"aeteResource.r Rez "{RsrcDir}"aeteResource.r -d FAT -append -i "{HeaderDir}" -o {AppName}.fat {AppName}.fat ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"DialogResources.r Rez "{RsrcDir}"DialogResources.r -d FAT -append -i "{HeaderDir}" -o {AppName}.fat {AppName}.fat ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"GeneralResources.r Rez "{RsrcDir}"GeneralResources.r -d FAT -append -i "{HeaderDir}" -o {AppName}.fat {AppName}.fat ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"MenuResources.r Rez "{RsrcDir}"MenuResources.r -d FAT -append -i "{HeaderDir}" -o {AppName}.fat {AppName}.fat ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"PowerPCResources.r Rez "{RsrcDir}"PowerPCResources.r -d FAT -append -i "{HeaderDir}" -o {AppName}.fat {AppName}.fat ÄÄ "{RsrcDir}"Supplemental.rsrc echo "include ¶"{RsrcDir}Supplemental.rsrc¶";" | Rez -append -o {AppName}.fat {AppName}.fat ÄÄ "{RsrcDir}"About.PICT.rsrc echo "include ¶"{RsrcDir}About.PICT.rsrc¶";" | Rez -append -o {AppName}.fat {AppName}.fat ÄÄ "{RsrcDir}"InfinityWindoid.fat.rsrc echo "include ¶"{RsrcDir}InfinityWindoid.fat.rsrc¶";" | Rez -append -o {AppName}.fat {AppName}.fat ÄÄ "{RsrcDir}"Mercutio.rsrc echo "include ¶"{RsrcDir}Mercutio.rsrc¶";" | Rez -append -o {AppName}.fat {AppName}.fat ÄÄ "{RsrcDir}"QDxDispatchPatch.rsrc echo "include ¶"{RsrcDir}QDxDispatchPatch.rsrc¶";" | Rez -append -o {AppName}.fat #-------------------------------------------------------------------- # Step 3: Compile dependencies for PPC #-------------------------------------------------------------------- #--------------------------------- The application itself {AppName}.ppc ÄÄ {PPCObjects} "{HeaderDir}"JPEGView.h "{HeaderDir}"JPEGView.r.h PPCLink {PPCObjects} {PPCLibs} -sym on -o "{LinkDir}"{AppName}.xcoff ¶ -uf "{LinkDir}"{AppName}.ppc.unref -map "{LinkDir}"{AppName}.ppc.map MakePEF "{LinkDir}"{AppName}.xcoff {PPCSoftLinks} -ft {Type} -fc {Creator} -o {AppName}.ppc {PPCRuntime} SetFile {AppName}.ppc -a BM MakeSYM "{LinkDir}"{AppName}.xcoff -r -o "{LinkDir}"{AppName}.xSYM delete "{LinkDir}"{AppName}.xcoff #--------------------------------- Resources for the application {AppName}.ppc ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"aeteResource.r Rez "{RsrcDir}"aeteResource.r -d PPC -append -i "{HeaderDir}" -o {AppName}.ppc {AppName}.ppc ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"DialogResources.r Rez "{RsrcDir}"DialogResources.r -d PPC -append -i "{HeaderDir}" -o {AppName}.ppc {AppName}.ppc ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"GeneralResources.r Rez "{RsrcDir}"GeneralResources.r -d PPC -append -i "{HeaderDir}" -o {AppName}.ppc {AppName}.ppc ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"MenuResources.r Rez "{RsrcDir}"MenuResources.r -d PPC -append -i "{HeaderDir}" -o {AppName}.ppc {AppName}.ppc ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"PowerPCResources.r Rez "{RsrcDir}"PowerPCResources.r -d PPC -append -i "{HeaderDir}" -o {AppName}.ppc {AppName}.ppc ÄÄ "{RsrcDir}"Supplemental.rsrc echo "include ¶"{RsrcDir}Supplemental.rsrc¶";" | Rez -append -o {AppName}.ppc {AppName}.ppc ÄÄ "{RsrcDir}"About.PICT.rsrc echo "include ¶"{RsrcDir}About.PICT.rsrc¶";" | Rez -append -o {AppName}.ppc {AppName}.ppc ÄÄ "{RsrcDir}"InfinityWindoid.ppc.rsrc echo "include ¶"{RsrcDir}InfinityWindoid.ppc.rsrc¶";" | Rez -append -o {AppName}.ppc {AppName}.ppc ÄÄ "{RsrcDir}"Mercutio.rsrc echo "include ¶"{RsrcDir}Mercutio.rsrc¶";" | Rez -append -o {AppName}.ppc {AppName}.ppc ÄÄ "{RsrcDir}"QDxDispatchPatch.rsrc echo "include ¶"{RsrcDir}QDxDispatchPatch.rsrc¶";" | Rez -append -o {AppName}.ppc {AppName}.ppc ÄÄ "{RsrcDir}"PowerPCStub.rsrc echo "include ¶"{RsrcDir}PowerPCStub.rsrc¶";" | Rez -append -o {AppName}.ppc #--------------------------------- Source files "{ObjDir}"Bottlenecks.c.ppc.o Ä "{CSrcDir}"Bottlenecks.c PPCC "{CSrcDir}"Bottlenecks.c -o "{ObjDir}"Bottlenecks.c.ppc.o {PPCCOptionsOpt} "{ObjDir}"CustomCopyBits.c.ppc.o Ä "{CSrcDir}"CustomCopyBits.c PPCC "{CSrcDir}"CustomCopyBits.c -o "{ObjDir}"CustomCopyBits.c.ppc.o {PPCCOptionsOpt} "{ObjDir}"GIF.c.ppc.o Ä "{CSrcDir}"GIF.c PPCC "{CSrcDir}"GIF.c -o "{ObjDir}"GIF.c.ppc.o {PPCCOptionsOpt} "{ObjDir}"Quantize.c.ppc.o Ä "{CSrcDir}"Quantize.c PPCC "{CSrcDir}"Quantize.c -o "{ObjDir}"Quantize.c.ppc.o {PPCCOptionsOpt} "{ObjDir}"TIFF.c.ppc.o Ä "{CSrcDir}"TIFF.c PPCC "{CSrcDir}"TIFF.c -o "{ObjDir}"TIFF.c.ppc.o {PPCCOptionsOpt} .c.ppc.o Ä .c PPCC "{DepDir}""{default}".c -o "{TargDir}""{default}".c.ppc.o {PPCCOptionsOpt} #-------------------------------------------------------------------- # Step 4: Compile dependencies for 68k #-------------------------------------------------------------------- #--------------------------------- The application itself {AppName}.68k ÄÄ {68kObjects} Link {68kObjects} {68kLibs} -o {AppName}.68k -t {Type} -c {Creator} ¶ -ra =resLocked -rn -sym on ¶ -uf "{LinkDir}"{AppName}.68k.unref -map >"{LinkDir}"{AppName}.68k.map SetFile {AppName}.68k -a BM #--------------------------------- Resources for the application {AppName}.68k ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"aeteResource.r Rez "{RsrcDir}"aeteResource.r -append -i "{HeaderDir}" -o {AppName}.68k {AppName}.68k ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"DialogResources.r Rez "{RsrcDir}"DialogResources.r -append -i "{HeaderDir}" -o {AppName}.68k {AppName}.68k ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"GeneralResources.r Rez "{RsrcDir}"GeneralResources.r -append -i "{HeaderDir}" -o {AppName}.68k {AppName}.68k ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"MenuResources.r Rez "{RsrcDir}"MenuResources.r -append -i "{HeaderDir}" -o {AppName}.68k {AppName}.68k ÄÄ "{RsrcDir}"Supplemental.rsrc echo "include ¶"{RsrcDir}Supplemental.rsrc¶";" | Rez -append -o {AppName}.68k {AppName}.68k ÄÄ "{RsrcDir}"About.PICT.rsrc echo "include ¶"{RsrcDir}About.PICT.rsrc¶";" | Rez -append -o {AppName}.68k {AppName}.68k ÄÄ "{RsrcDir}"InfinityWindoid.rsrc echo "include ¶"{RsrcDir}InfinityWindoid.rsrc¶";" | Rez -append -o {AppName}.68k {AppName}.68k ÄÄ "{RsrcDir}"Mercutio.rsrc echo "include ¶"{RsrcDir}Mercutio.rsrc¶";" | Rez -append -o {AppName}.68k {AppName}.68k ÄÄ "{RsrcDir}"QDxDispatchPatch.rsrc echo "include ¶"{RsrcDir}QDxDispatchPatch.rsrc¶";" | Rez -append -o {AppName}.68k #--------------------------------- Source files .c.68k.o Ä .c "{HeaderDir}"MPW.Header C "{DepDir}""{default}".c -o "{TargDir}""{default}".c.68k.o -s "{default}" {68kCOptions} .a.68k.o Ä .a Asm "{DepDir}""{default}".a -o "{TargDir}""{default}".a.68k.o {68kAsmOptions} "{HeaderDir}"MPW.Header Ä "{HeaderDir}"JPEGView.h "{HeaderDir}"JPEGView.r.h C "{HeaderDir}"JPEGView.h {68kCOptions} #-------------------------------------------------------------------- # Step 5: Compile dependencies for standalone 68k code #-------------------------------------------------------------------- #--------------------------------- Link QDxDispatch "{RsrcDir}"QDxDispatchPatch.rsrc Ä "{ObjDir}"QDxDispatchPatch.a.o Link -t rsrc -c RSED -rt xPAT=128 -m QDxDispatchPatch -sg QDxDispatchPatch ¶ "{ObjDir}"QDxDispatchPatch.a.o -o "{RsrcDir}"QDxDispatchPatch.rsrc #--------------------------------- Compile QDxDispatch "{ObjDir}"QDxDispatchPatch.a.o Ä "{68kSrcDir}"QDxDispatchPatch.a Asm "{68kSrcDir}"QDxDispatchPatch.a -o "{ObjDir}"QDxDispatchPatch.a.o -case object #--------------------------------- Link PowerPCStub "{RsrcDir}"PowerPCStub.rsrc Ä "{ObjDir}"PowerPCStub.c.o Link -t rsrc -c RSED ¶ "{Libraries}"Runtime.o ¶ "{Libraries}"Interface.o ¶ "{ObjDir}"PowerPCStub.c.o -o "{RsrcDir}"PowerPCStub.rsrc #--------------------------------- Compile PowerPCStub "{ObjDir}"PowerPCStub.c.o Ä "{CSrcDir}"PowerPCStub.c C -mbg off -r -opt speed ¶ "{CSrcDir}"PowerPCStub.c -o "{ObjDir}"PowerPCStub.c.o #-------------------------------------------------------------------- # Step 6: Dependencies for the MetroWerks resource files #-------------------------------------------------------------------- #--------------------------------- The resource file itself Resources ÄÄ "{AppName} resources" "{AppName} Help" #--------------------------------- Resources for the application "{AppName} resources" ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"aeteResource.r Rez "{RsrcDir}"aeteResource.r -d FAT -append -t rsrc -c RSED -i "{HeaderDir}" -o "{AppName} resources" "{AppName} resources" ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"DialogResources.r Rez "{RsrcDir}"DialogResources.r -d FAT -append -t rsrc -c RSED -i "{HeaderDir}" -o "{AppName} resources" "{AppName} resources" ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"GeneralResources.r Rez "{RsrcDir}"GeneralResources.r -d FAT -append -t rsrc -c RSED -i "{HeaderDir}" -o "{AppName} resources" "{AppName} resources" ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"MenuResources.r Rez "{RsrcDir}"MenuResources.r -d FAT -append -t rsrc -c RSED -i "{HeaderDir}" -o "{AppName} resources" "{AppName} resources" ÄÄ "{RsrcDir}"Supplemental.rsrc echo "include ¶"{RsrcDir}Supplemental.rsrc¶";" | Rez -append -t rsrc -c RSED -o "{AppName} resources" "{AppName} resources" ÄÄ "{RsrcDir}"About.PICT.rsrc echo "include ¶"{RsrcDir}About.PICT.rsrc¶";" | Rez -append -t rsrc -c RSED -o "{AppName} resources" "{AppName} resources" ÄÄ "{RsrcDir}"InfinityWindoid.fat.rsrc echo "include ¶"{RsrcDir}InfinityWindoid.fat.rsrc¶";" | Rez -append -t rsrc -c RSED -o "{AppName} resources" "{AppName} resources" ÄÄ "{RsrcDir}"Mercutio.rsrc echo "include ¶"{RsrcDir}Mercutio.rsrc¶";" | Rez -append -t rsrc -c RSED -o "{AppName} resources" "{AppName} resources" ÄÄ "{RsrcDir}"QDxDispatchPatch.rsrc echo "include ¶"{RsrcDir}QDxDispatchPatch.rsrc¶";" | Rez -append -t rsrc -c RSED -o "{AppName} resources" "{AppName} Help" ÄÄ "{RsrcDir}"HelpText.rsrc echo "include ¶"{RsrcDir}HelpText.rsrc¶";" | Rez -append -t HLP! -c JVWR -o "{AppName} Help" "{AppName} Help" ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"DialogHelpResources.r Rez "{RsrcDir}"DialogHelpResources.r -d FAT -append -t HLP! -c JVWR -i "{HeaderDir}" -o "{AppName} Help" "{AppName} Help" ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"GeneralHelpResources.r Rez "{RsrcDir}"GeneralHelpResources.r -d FAT -append -t HLP! -c JVWR -i "{HeaderDir}" -o "{AppName} Help" "{AppName} Help" ÄÄ "{HeaderDir}"JPEGView.r.h "{RsrcDir}"MenuHelpResources.r Rez "{RsrcDir}"MenuHelpResources.r -d FAT -append -t HLP! -c JVWR -i "{HeaderDir}" -o "{AppName} Help" \ No newline at end of file diff --git a/New in JPEGView 3.3 b/New in JPEGView 3.3 new file mode 100644 index 0000000..c9fa74b --- /dev/null +++ b/New in JPEGView 3.3 @@ -0,0 +1 @@ +========================== Changelog for JPEGView 3.3 ========================== ---- Bugs ---- (fc1) Removed the unnecessary use of the Time Manager to measure image drawing time, simply counting ticks instead. The alleviates a number of system-level crashes that would occur if JPEGView crashed during decompression. (b5) The "Startup Screen" option in the Save As file format menu has been changed to read "PICT Resource" so that users don't get confused as to why their compressed startup screens won't display properly. (b5) Small image files (<600 bytes) would be incorrectly reported as invalid; this has been fixed. (b5) Choosing to crop the icon only when saving, and using proportional icons (dog-ear or no) would cause the icon cropping not to kick in. (b5) The rectangle the icons are drawn into is now inset by 1 pixel, so that the 1-pixel black border around the icon doesn't overwrite so much of the actual icon image. (b4) An unresolved alias found while searching a slide show directory would dump JPEGView into an infinite loop or cause it to abort the scan of the current folder. This situation should be remedied. (b4) The Inited flag is now cleared when saving images; this seems to force the Finder to update custom icons better. (b3) The JPEGView JFIF Preview has been recompiled yet again. It is now a true fat component, created according to the Component Manager 3.0 specs. This should hopefully solve the occasional weird problems I was getting with JFIF previews. (b3) Slide shows with virtual memory on no longer allow offscreen bitmaps to be created in temporary memory. This results in more paging than with version 3.2, but it is quite tolerable -- at least on my PM6100/60av! (b2) Certain color startup screens would not be displayed properly if there was also a black & white version stored in the data fork. JPEGView now checks for a color screen, and ignores the black & white one if it is found. (b2) Selecting the Desktop for a slide show scan finally seems to get it right (I think!) Also, I put in a check during the slide show scan so that infinitely-recursive alias resolution can no longer get you into trouble! (b2) The dog-ears on large icons are now slightly bigger, and should be comparable to dog-ears from other apps. (b1) Revealing a hidden part of a window during two-pass color reduction of the image in that window would abort the quantization. This was particularly bad when doing the color reduction during a save. (b1) Somehow, bundle bits in the Finder were not set on the version 3.2.1 I released; this is now done explicitly during the build. In addition to the bundle bit, the shared bit is now set so multiple copies of JPEGView can be run from a single copy on a server. (b1) There was a conflict between the "always require bitmaps" preference option and the "no bitmaps for uncompressed images" option -- that is, JPEGView would complain it didn't have enough memory to make a bitmap for an uncompressed image, because you told it not to :-) (b1) If you had selected a slide show folder that was on a removable medium, JPEGView would prompt you to insert that disk everytime you started up. JPEGView now does a less-intrusive check for the existence of the last slide show folder you chose, and if it doesn't find it, it resets the path to point to the Desktop. (b1) Some people were detecting a write to memory location 0 when quitting JPEGView. (b1) The QuickTime VM patch would sometimes be incorrectly installed on machines that didn't need it, resulting in a significant slowdown. (b1) When scaling really large images (>1000 pixels in both dimensions) down to icon size, the very high quality drawing (which I use for making the icons) would sometimes crap out and not draw anything. This was due to the fact that when a large number of pixels in the source image contribute to a single pixel in the destination, each pixel's contribution could end up rounding down to 0, since I only kept track of things to 1/1024th of a pixel. I have since modified the very high quality drawing to retain resolution down to 1/65536th of a pixel, which appears to solve this problem for the most part. (b1) The Select Screen Area command would not be available if an image that would have fit in a full screen window was instead being displayed scaled in a normal window. (b1) Printing images to the LaserWriter 8.1.1 driver seemed to go awry somewhere along the line. This appears to be gone with the new implementation of the QuickTime VM patch. ------------ Interim bugs ------------ (fc1, introduced in b1) Dragging a selection so the cursor was outside the image rectangle would cause an unimplemented trap error, because I was failing to check for the Drag Manager ahead of time. (b5, introduced in b3) The JPEGView JFIF Preview wasn't displaying previews properly for files with type 'JPEG'. Files with type 'JFIF' were working all right, though. (b2, introduced in b1) Fixed high quality drawing on the PowerPC. -------- Features -------- (fc1) The comments and statistics text can now be dragged out of JPEGView and into another application. (fc1) Progress dialogs and displays are updated more frequently now. (b5) A variant of the Independent JPEG Group's JPEG decompression code has been added as an alternative to using QuickTime for displaying JFIF images. The IJG code is much more robust at error handling than the QuickTime code, but is considerably slower on 680x0 machines. For this reason, QuickTime is still the default for 680x0 machines, while the IJG code is used automatically on PowerPC machines. If QuickTime is not installed in the system, then the IJG code will automatically be used on either system. User control over which code to use can be found in the Miscellany section of the Preferences, at the bottom. (b3) A new preference has been added: icon styles, under the "Files" section of the preferences. This allows you to choose one of four preview icon styles: square or proportional (a la Photoshop), with or without "dog ears". Hopefully that will be enough to please most everyone. (b3) The scale AppleScript property of an image now accepts integers from 1-100 instead of fixed point numbers which AppleScript doesn't know how to deal with. (b2) The File Format popup menu is no longer displayed if you are saving a non-JPEG image. Hopefully this will stop people asking me for an "unlocked version" which supports this. :-) (b2) Added a new mini-popup menu to the bottom of the save dialog which lets you do something with the currently selected area of the image you're saving. The options are: do nothing, use selected area to specify the icon cropping (it still has to be square for now, though), or use selected area to specify image cropping. (b1) After toying with a version of what I considered to be "low" quality drawing (i.e., really fast but pretty crummy), I discovered that my low quality was actually equivalent to my high quality in 95% of the cases. With that knowledge in hand, I rewrote high quality drawing to do "low" quality drawing instead, and came up with a good 20-75% speed increase (you'll a see 5-25% increase overall, including decompression) with very little additional quality loss. The high quality dithering is still included, so it will continue to be labelled "high" quality, despite the fact that the scaling quality isn't quite on par with Color QuickDraw's. (b1) Due to the above change, the default drawing quality is now set to "very high". (b1) Display times in the statistics floating window are now given to the 1/100th of a second. I was mainly using this for PowerPC benchmarking, and may decide not to keep it in for good. (b1) On a drag-aware system (that is, with the Macintosh Drag and Drop extension *and* a drag-aware Finder -- e.g., a Mac with system 7.1.2 and the extension), you can now drag any folder or disk icon from the Finder into the slide show options window to set the slide show folder (very cool :-). (b1) Dragging a selection outside of its window will, on Drag-aware systems, allow you to drag and drop portions of an image into other apps, or into clippings files in the Finder. (b1) Updated the operation and use of the internal QuickTime VM patch, so that it now allows the use of up to 512k of temporary memory for image decompression. Its effects are also now disabled before giving time to other applications so that extensions that need to use temporary memory can still do their thing. (b1) Opening PICTs at other than 72dpi now expands them to the full resolution. (b1) The "marching ants" used to indicate a selection have been redone completely, and are no longer rendered invisible in medium-gray areas of images. (b1) Once you've cropped an image, you are now allowed to save it; when you do this, however, what you are actually saving is not the cropped image alone, but rather the entire original image plus a 'RECT' resource which specifies the initial cropping. Thus, images may be cropped for better viewing, but may always be recovered. ================================= Remaining "bugs" for JPEGView 3.3 ================================= ---- Bugs ---- (?) Statistics for cropped images saved with previous versions are messed up. (?) The JPEGView Convert To PICT script saves palettes for grayscale JFIFs. (?) JPEGView's progress window can poke through the Finder's window when running in the background. (?) Dragging windows from 1-bit screens to deeper screens doesn't always force a complete redraw? (?) I've had two reports of bugs when running a second slide show during the same JPEGView session. As far as I can tell, it's linked to selecting a different folder for the second show, but I can't reproduce the problem at all. -------- Features -------- (?) Modify the way the slide show works internally to read any number of aliases from the specified file. This is in anticipation of the future, where we will store slide show information in a separate file, allowing multiple files and/or folders. Although we will put in the code to handle multiple entries and external files, 3.2.2 will always read from the Preferences file, and will always find only one folder specified. Consider it a step forward. (future) More detailed preferences for specifying dithering, display quality, and color reduction for each image depth. Something like this: When using... Reduce colors? Dither? Quality? 16 colors x x normal v 256 colors x x very high v Thousands x very high v Millions very high v \ No newline at end of file diff --git a/Pictures/Atlas Rocket.PCT b/Pictures/Atlas Rocket.PCT new file mode 100644 index 0000000000000000000000000000000000000000..03bd6afdcd1e4080f17d36f7ec9172618ecc0345 GIT binary patch literal 50952 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 aCH@7q{R)6hxc~?N3_oxmls^D~fBzp8W4H1E literal 0 HcmV?d00001 diff --git a/Pictures/Earth Color.PCT b/Pictures/Earth Color.PCT new file mode 100644 index 0000000000000000000000000000000000000000..c95e6bd0a3ee99517a5bd161832c3656fe1a604e GIT binary patch literal 87960 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

    v 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 Le&L>>4kG(M5l3Wx literal 0 HcmV?d00001 diff --git a/Pictures/Escher-Snakes.PCT b/Pictures/Escher-Snakes.PCT new file mode 100644 index 0000000000000000000000000000000000000000..e42620c438834cdfecc40691e61d9c834afe1ed0 GIT binary patch literal 90242 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 R?G%M(I8@*mz>j|Nn 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 literal 0 HcmV?d00001 diff --git a/Pictures/Hubble Deployment.PCT b/Pictures/Hubble Deployment.PCT new file mode 100644 index 0000000000000000000000000000000000000000..df2376f5edaabba904d974046f41f0a0e8b6dd87 GIT binary patch literal 61008 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 literal 0 HcmV?d00001 diff --git a/Pictures/PacMan.PCT b/Pictures/PacMan.PCT new file mode 100644 index 0000000000000000000000000000000000000000..3b49a1081f338e6df42192fdac8cec36a75a6bde GIT binary patch literal 51966 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

    LpPX};wh#hJKIx1MsgDx(H;bzUN> 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 z

    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 literal 0 HcmV?d00001 diff --git a/Pictures/Star Wars-Death Star.PCT b/Pictures/Star Wars-Death Star.PCT new file mode 100644 index 0000000000000000000000000000000000000000..76e5b376ec936ba2374a767201055120d4a97e66 GIT binary patch literal 65318 zcmeFYeLPeD|37|a7?O)jZ8cX-m{i8fhB4%tVbXMQsVbm^KimI)H30md>VL}7(D1WC|5X)lK>)}vJp96c?Mna>r@-$2 zt3PX&07%|F_)_F0&3&3q?zZ;-^KbuKMf309zr%mW0VO9pM>_x{?vnVN;;WAUHh_$@ zG(=iT1_FV|%F4*eL$}Ir*&+|$rlJT{+o_?hwiAKS)ZVYFx!VAVKEL6{pTbgSy@^6E%LCfTVY082rZ-k$K`J;pe*yBTMh>81|*b0U}ezX*MNq& zpHiUzR{jSVkOWv#N*W>~E4M{_K%){M0Rn?1B*9Wrl9J-16U6O+q_WgDEwq)iiiaO$ zHyLV_oLwq|w61ScCH4Q%HujH5k(JxN0|wu@M@Lr=rH?sy$OMZswK;5SXYb(XN38h3vMaRU(QB$v6y_R|x=joT694DyVNWGnll8F?dE z4Wj;w^RywoEHtAGEC+$}EM9m^+R_tH5yk`R4Nns&qVk18fO?p}pjjzr6frE|z-Ncb zrsE*c^2K(`H{Hg!y+)E7iis5BOXS{UCsx&ON65!K#qQ!JAgERr93UaUvKR?}Jb!lt zgSFL}?~Wf+QNwS=zXSb-)wT8>LkO~ePhGWknDu^~h!{KoMBRKtXQ^{dv{)x4!#c4dPp^TOrA+C zIsNV?M_YvPx;s>1xE277Zmrer7j{^Y+z3SDU!uyufpZMIjMFGM^-8$g*TGHI{o77$ z@$y|cYjh|F+gZNQgRPp!AxI`1gj_BG*akur+DQ>*xC4!N1sGa`7~&xBXjw2-lrnu? zdAVo*sCq2tB7BD12s&AKbPF8-%{eC*Lo~ce#!N<@-W#f7Z$WApbumpXj6*|`< zZI{>})$xqxY_f?jn$Jjqv5aLF>`|D!Mv_5w*6g=<(>KnMq3a65t z>DwSqzL>@IaG@nzQx^kzPxnvWLI*7=Rs^?>k1vkp-lwFKIH6e_2ogI>0KmF1mZD1n zs?96Aph;flWp-Bu1KqP-;<%b`zFOG{i8`}gW+#UQ5U4}j*PtUZH4#vit83@(_S(B$ z=u_A+OHkx?I?RpH=^zHV9m8Cm{YXdm+J(@**U#CF>UAQ``>2x&t|-WTOMU;Qg08>7 zPBl2}8i0`3s4O?%>Cs^$VIM|zkWPI+#-OgSM|e(h^qj3=C22f9exN(^%wOQtK}C*t z);I?cY8M(f2m1O>Ch4F46kEoi@bi|Iq2DE9z60f3MdPHatMIZ*555vwm2i+nR_5zJ z{OnFmM({}P`xZb4H`@+2W5luBg!mBjFLzDLOp8JJ_=#Y`%{ zZkxlmJxO~?-gJ#LEzuX5F{S6C!nFNFp_z*l%pE!fH-=We8b6%yTEnUC{$}#c;^at{ zVtMW6L9Z+nIM$CAVLY>8N}~Mos61mWVG*#rU~jcRiVJhDv$p=3(7fOwZ1j!Vl7eRX zGW0s|A=1>KCH95r-e9FG(rOP)`Qyx;Rvig5tzo+SqAOZ$h(J%m0?#`RE=k`>kX6I7 z_M5=rn|b5S7{EdJgAGQ6qtd@54@Z^3diFykV>k+|0G%qWt-#}i#QY>8f2sv?!vs1x+ugXeD9@ua5U0=RA(sP!W*cos%2H#k$Hb3+2tJ-`l@U(4i6HXF}(q`UF5 z8IC%S%5veIooj>r-N(PfEs2evBy%3(bff3rbWgWt+VJxn6#sDfRrgYJ8%mPgLJPrn zZeRtRp@!xhZ$?~7$B8;hA7Uq)Vk(%tagssSbbEkP)9n3?FlBV`|)Uo&*I^RbWqqq9d0 zUFJ6fmu890{F-@Rh3cUtP4KR8huKa%@%%~qhfkX8PP|24xbj1wt>F_rv-a-KpR{*Fb-wqXrm3@j z*f&Pr{`itGFl-)zZ$h58`=$9KLeXNgu}78XZyV9GcRJehVy$~>?o+zZBF|U-g||nm zpmM<`V6m#6MHQ<3>uL2d*7B+)d_1xuJ1dTBkvE)`L0{}!DaS&x?evh4`>uNxCdMOx zsjTD$=QiX}ii~96-n5IauspU}bNNh(OaHeJy7i&esoReg5@yg{Q@2YxXgb-NhqbhW z{HrN+P9 zK7q2{$ynpf`r@>+xqS9g`SG1f-;w9!yN0tA6u%{zW)@S#mZEEB&dx00XITY>>rGUw z1#25V)JMYp(@+u?ASI;i_EP(lrJYXnzL+-6eNXKu*S znIabbC#sbhHBO3JTO`aMSSmy8bVsZ;@V&AO^3%n;_r@3;8g9g?{}Y~ zU~t?$cgy^FE)Dh15yTvigE5m2l8nBG>!;!_zg7I=(FUn?o2u5h)2FdYt2uV(heW-* zH1?pn!oq2@LbjP=DgWaemFzUqSo+I`yO~DUP)!PP3qE!~Vr$jRju!UX8n|RfexxRU zKYx7aq*2`I>F*K?0XfhEgoLCn4n~XSTOEh%>ZKmB_R1%D?Y#y{Mg*-ddUlM?3O@@LI{ydU&^8AHUu9py*az9#qm$BdCR2%o^fBKrW3;z4x%~PBC z*75Pq_fpQCJ@=t5g99Ko)3nL&59SG?D!y{=KUE6(m;L-M%&wabin!Vg)=WUt$vqYV zm%_DvLHd+9b~v;v0)Y_W6^ZzJ+g9)*vc%$D8~Nu5YPMIb<=^iKi6*QkAc{-3Ph#sVLi-+2l7cEc)%{)a{;W z{pF}LC0lcCfM9@~JNBT~f~N-@Iw=p301}J7%@O|>(64$@;ii4`kZJC}a9$$X&McY( z`aM9-<|kjb(&gZ*%5xkAIwg!d*!2*$0}Jx|WOhkJM!AGpVbG5`UdvvUWCD*3m;em7 zS;yYkcI?l@YyWgwUe&s88j$(b$&OO!j{XbGmO)>Bd34F6YerP=8xq&H)@KKKfst{M z58&s*ES(BZtbe7e+Ws5}{>Tc-i69Ryy`S+2u*?8k(dGMd&~CBXS1PmNHhO-=_4uoivxlfO>LcXAIoq8B(98&MN85JG46QOur(z&9l(?;nDV8t zJPuWZT(Mu#XS3ngGkSC0i%({Ul2@Mw;j5}m0~3Nf1~&BS?rVOHRh!mrgh8rU481xZ zq5{5Bh_81`-+m{(!br8?D-8zZzMpaJ2$p_5ZK|-<;_z^|+8KQXyIAeW$>?%qriTLr zvDqMl&UU7IWY#)Aw$y$+wPX^oE4BkqS@WkgD^Dglh0l^?`d$;KmW&53!IpcI*!H}{ zyyLFPYS&Er>FVX~uYUIdLN;0k0_P+`ev}PTJ?J2ZW3a?U0WFw|NHQf0EWKTV3ft8T zLVPqRa|Ez?n8y^@mp=W$M zk`Iv#NWoTH2L>b`-N#z`+V;iXo1XBwASN^v8{ZFf`R>@ z=ar}bQa$0a+7eD{>0U35?tkBgg{JdgvPSK;Iy`$!ZmswMRh)pR>RJE7!4LyFLYvZ4 zn8!R>%kT`&@Lyow3K{U{rF9C7 znVcTRJlpj9<2U~|EbD=iLlgeLN9f ztGt7`W&1JB7?(e5$tPAHcR$v&#b%Vfxp-OXvhw@lXUv$Xhh&fES5LK^=ZLZ-eU#YtWmhw#+Z=75#sCAW^IsEDsj84yGN}CHSd#U0O%XqGy zc<33e4(G1zQA}Z!^geoM75}h&_2;*rGTKj$T+SysfGEYAAJ)mok7d1*udH`?8=djz z+My?8?_(+GC2f+uso~kPzTx84CLwNl;vr{jz_?o`Xb&TP>f!A>{jMkd4U`lyGzpnr zv~wW{l;Bu(aOVz&T>`2+p5i9VUT^|&EA;B-564+FJX>XV;3jf^g&eA^B$ z7aTu-#?MG7DS9{&fmUdmW(n2ZC<2wLly1X2owuGv#6l`77Tdu}0cx8KEEQ3i#tpVR zxgF3F)@ll8+2Tjn_xlP^BjK)zLcwEA>0 z$-`H}8_mOf-Tpu^BVzZ#C-iWjww^Z4O`R6FnKvdJDr%s(T6|`2S1RK) z>eJjXVn1y?gqqEC-^wrtIoR1cn{PYG(>AI)f%LC=eg&cIqPYp(cG#*TiH(hfv5^va z0kwcG3_q=@&Pw+IClj}nxb-Ic*k&I^1)z~TkP4K1E(a?dJ#sjJjs3x$bx1(B)_4rQ zdUDz#ujDGC&otdYD@kk4DR!<0+9W7`;pD5Uo15;L6XA%R59VTd77YL~G^@t(0;^lr zTp@I{sGebZ#BghU*fMVIU4cOUn1K<|=`UbG** zd#7Sz(=}NSJ^a%3HRCnCIPdMVH%qDsrY7!$Nu>nJiTZoW>&TL-+LO>7hZZip1xIw^ z6O!^tg({)1RW&Kz*y%f4KQtT*M=lIfJ&#EH{z(is+^VPUH?{$>a%=^JRWrW^joxun z6yJOvVt)hLc+@lqQ$2K2?va%6E6+TpbnlI)J8H_5T6Y<2VV2Bz+qP;lmGHABZ#z$? zCUe<7khnJp>c;tpJNLrIzP~`UqRE-3i53lyGI1cO=ZlaK-ld^?ni9s%gEYvQ&6eXY zwGC7TC->W*VSBzie%_vZc!$UJBAuU$9nj(zCP^Jtyf1&=JdtoNHF?{Mn|50KJSZ2} z+@y5<%T2{B?pu898p3zt)~-*E5p%oaZZKJJSXa-VmNww!%He7cd`Sb*r`80bdg(_-4KYObd zI%Tb5@H&U)yVPd>7g)ZBRIB!We62qxr-{OY7D?l)TBDGdK=o(t?n6NCSe6JU;ymwr ztFp%m+u7D`45fu(C;4*ZS;tfdfB7dZdN44y42HLKf>1#>e!0h|lg!cyra>QRJMDc2 z>Svr8MU@@s_U$lcx*MejB`HrT288Mj$88AfGl|dm$ypRf5y!VF=qD%hw54enMZ`WG zJL>{*C{<8RRrGMAD^e8`U#9YtwZT7Ft24hzK}&aO3TcgyN^U5c8P8A7B|rjt^td*z z@OG?k6bq*4;!h8Zf;MxtDOUK6s_SlVYO#AQoKn2(h!CrRwE?pU<`#K+c6MeZ3nroH z!5hjr-Y72K?ke^gh5P5h*CyyKR+v_{DS|3PHW$`y$QW%}Mgr&_7)|OdM9Q$mSC7ux#vq zPcUJCU7zDLF}B=15i=TiE~_2e$%f72D#TG(v5|4+S1W@|L`kh~Ej9|@%o1(pXAgBG z4`2d*d;S~6ie5;MRx039NwOTJSl;QoS&F^MGN5HPScj%qYfh#sygRDe#RoH<`H~k% zukXX^aN3B#Bi;1Yi|QiL^%Q3b86?86o;ye&{sP>X~2xvTOx~``WN^n z4zEL96}oC&b?UAT!tN`jBt6%M)G;hygcpw^R;$~i?F@&1w~*TnLYw?y+lZ*K1Er?5 zcaSycAipufw^)wt{!g6#r-LfBe7kYb|v1>>B^E=Pye+!=9(nQ-;d_{0j@7Cm;K3yrf zx7v>ej=Z?yX~?m%v~34U;sy#Z<&a z^^@c1>0Oc~-orWF&S~oBw}XpY%n*vLiBb8Kupg&NcE9ha43>dVc{EJBY@090KgdFJF?oG5#}o^r>?+cJmJV&^i1| zy*C%Nlbh%Y&z}$SqyN>qXJ(}4ZDw{)RaS4C-p87@Yvd7@>YJVrZFz7Wu2;s_>OSM7 z?@{9eRbb6!p4wl4r@HfFJ4&-H=jro+-iX)*p4IQc?)@%&Ross3o~!5NTM-K7k>vn* z=*j(B_&y!w*B)>aqm}V6jrR{KYqZ`M_Id=*Tp8@hay0)bg<-fI)andl4meB>7Dnx& znMRj)NTY_og_uo>*uE;9=X$MNXtTPgh&)4VRkP$^KsjiVL*>zewa|mZSh$=6AH~;_&Zq%OYJ!=~_Qs&Ze%!%4#FzwM28*rxK#2sn{R( z)m)h&*|qJ`F%(GpJ({5}&I}cTc)$2djKS9!{tu$5XFc~5jCFs9x%-ZtvAQi<=DC}; zSa}f?z;^1c^+`k`#N3LulI?zM`A9Bf@c1#%?>;Nbe7yxHyLfjnd0>dyM)_Hf1Xpsg zQ@P*trpce#hJa}Rdq3a)zL~pmYWw~%<5`022pg+l>W<^F;mc|Xl}Z5`-qwj>X+Jp$ zpz;8EG|L+C$K6Uyu*UC|M`RWRF-8Zd#e;xv@w0TFfLb}@b~E}^(UsS5Y>#~SaBpm{ ztt7b}3F11r0*dZrqK1cqadC;$Y5Sr4tKojRojr0UNy{@hu`S1fH{;zU=3hcT8fQ@$ z_GiQ-$Wi1IOCQhhgplqLYEVh&Ar%;C&(rZWcMB#zIpcGNo@45cXVaHV7#;;`WQ_6tm%WoK z5i~N84@r+0bE=VE=E6r)D)UJvfw>J^Qzb7SW@g?*p?|`goZjlgPD+=iqlNGp*Ax4? znRDZ!Et>~@DtCavIKN+{YCSu@*}lwLlGgVV$DU}pR5l6WkO4-CH~G(A!38qF0_Q{| zX(WcSu3z(DIB=1(ZtmUX*Y*(9>eEeBzgwPdirN_7}21Na@e}rCwwBhhYspSc6TBu{_ZsCx0ULEj@;g=1ASyeD6s7F})?U3qr& z{N4uzzSdOm2Vzpzee?0jW3~yV|LA7JuLmM?nSqLn_hadiHG92<#GNYvme=W|>icoJ z;M)Ctvb?2o^Qg5UU5EY|2LS&g(F>1CMeNcPW;@uqNhIH( z2Vnx5IO>E+vV$FjoaqfXK``aw3_(MxLjcg$gH+s}5$>-5d5;)i z(_iiFIB~p8IbSPzO}P!KzavYZoV^@SYly@TFd%%z6eaZG#LwPG5XaZcsaV;>l7R8d4>VO02-&Eo&MJE9BtDhanz?_T5%9Uvsw|d&o zxVR95;UbQbw3wluOwDGX&|ov8>POp@{3yeLB~z}(&(Tg;HWnv@oF!BrsmK0)h)&HN_|d*Q1p;fgI4;O&Wq4@nm)A)~5VR@N5teektE~M8IBc!& zdcE;9Z2o!D!B$EWiieMA4%;hekT84Dee*fu#o+kf8Tqyxv2 zTzE_H_Qnm8bkcQy_SthJYo@P&(I9{QJw8t3i`xy}t-rt_BZ$q%$EO(5%gwN3`d|N5 zaNJ#S!)E^L!yPn;_kBcugwLeL()x^6OHgOf=#Hum^78UQXS;n}fv0YVDiEzF@~*-@ zMkt2*7TPfDv=tOU6{aPIISX0Mo!Gga9d$X)7GGbEUmoTi)YS3|;C`Bp7gd)|D8ydQ z?s}!N_HIjy-T4!N*B!hqzl=wf_P+6WnVVO0GyD~WcKBv?r|0m{#rBQY2J~-7a;yYT zRHF`j*d1ckiPbNA;?2#Oit#lukrad_+{1NuohX8`zUscsepGR);rpMwt31!KhQORd zg@$uW2R{7;o?oS`P*YB3J)GayD{JvWxLg%>NlTA@FUJbGwR1zi%p>C4^6n#NENklolk(==7O~!3`czsGZ(YUa$?%BUePJFcwt)y27-_`Z% zvJ)nCPO0>m{cocCLig?L$tYVeFN&YIQ~Ah;lXpqt%Ws~`#`#0D67wV;e1D9Df;isj zaoyFfci05|0M`an!!3CB#8+5&?Q+~PTwC;f!19if{Pxdu=6IAyJ>P%C)8gnJm$-tj z($@5nGZ&7?{5aXV#iz_TAZ%B(qB$aHtkMmaUl7*4U#6R>zSp691l}-t=IIND?G=Yp zMeeB#g1=>cfL)-YVo!5iD-NJW9@LY6OSm9lYmqpsv=mEIlF!FS$M>lEpAdcu^Z%45 zZwPVmI!$)F@V&!gaakmeat0&ske&3biUn*4Y(>O|BMQSDa4gm`J|up5lB7W43Z3kX zf>k><<5|H2U@CjPe6?%>l$lQau8CizywUl!SM94`?E_P1k>eia6#j)sO^D=nu zcIxUQZX-6rkV={;@CkCWPAEj29J1~tec7#b!Rj#z(uKUnyZ8&!~^|Z=ahqrIr@7&Oy%pK)FyLJLT zva28`91u=p%hlr8zWxe?mGZV_i@^nscMi6kj5KihMl;STzX}KIs!2O&Wa#Wx633dL z**W6KH33px6j1V@b~}h5n)#Rl(#52{M|gI)UGUoW;Y_KecQ~NZ1DjpO1mJN8dl`?V z!tFy{C<{a{145_z9>m|&0g zn6UW{N7$uvZ9KOJ!sF3TP9I4N+SP=tb$nzjefD<*!E-wF$jY8R$EUaM3zLzT_LPrB z0H3mls>-BtCyycFd11W?Yve(>Mhd(0&Eq|~YJgvQ`J&Isw{;kBqKw9YeeX+>HXB{$ zi!1V)eJv&y~{mM@D;NObVrO zpc@vcg+r=Gdl1Xv^XpxO$~Dt(JFFTaj7;U)|IHgc6;}h+`_}wzuN}OiP#4{`bomt{ z-V3$w)1>U9bK!ESgEXAj(fKtvc=?T0zmw7Bk^BKi z>>lks{4gY!TmR9QZvwUykaV&W-HsQ4isNdxL|)tFdp7$mE#LAG0Ve>@WDYS`vl=81 zk2~Pw)B8O$8jYf=P0l{(tawba4Q8J@@iRtG?S-;O98uwf+Zm_&gCozr6x;_|lZcj7*H}s>~Y~_X8%mGF8mg#dgGdnjOi@Z;%ga>J4GX^(L(iF0S#_ zDLvcOI#TR{aonNX0BFGqz9t8@0%mf5k+L(F3Q2~E4J~d}b1u??_fRPjn+wJ#=*_fC zY(INAe+VU?of2K|vkg!FSRjpV-*2ig7!h(@N=Dvg(_f+-NHhEA0TJC{>3t3dv&?3% z^ys6`xtkW}ecyYdb>cQAQmjI7nV_lW0X48~RC;6u%?@Ab?nZXY!R?O7K^;}IkyrlZ z;kQQTX`joY|M9Fdq72lvYpD-@2hk@dmlo_ooP-=J`>F-oO~QgUZ&8J0x?*ljGaMSxaI<2Hh|t+6aL zKnqut&hyQ*AwU6E7G(re9vE4EdMlP9_L^D8RB(dbOh~ORF(r#h^{hW|6hl|}T!?1m zwKxh}5R@KYMh7NJU8GFxK&M;gOYEZi=MH=N`cl&Ofw+sr3bh+nk{?N97dj}du{DDIRz^ae!^r3u$%fQ-@qwhX{(U-P- zn#xbr@=^5%mZus*@V#ETJ0iPZ_-D*n1bR(3pZ+x+8av0zuo&OR44Wp}{{^bcgUsMo zKwvg^b~7R5rfyFsBy)biQMUW!Xz8A3i>B9qk&J0%-fxLo?zxA^PJz+hZE!;CJv;2k zFS7tV$_BLSu7vF5;`_|aM#S~7GUIC*kXzq7O)ND7l7GE(`)+-tOJnOWaQ^&ib=kZj z{)e5uX77WBymixo$nmvp_Xb_R`9Ch9gpL0N6eaU{8rk>IsaX~S%94QPW&7oO$8uY< z3#QDRQ(J|9fpcmgH=XwPn~r~S7&|vfzSnxV|f=szt*B?%yd@qLDIJ+PUDc0ku=&I-0*XPPc8vs$5rW|DjrM1m~68A8XVxw|w3 z!wUM{pIb-(6cVC0}!q={YCZO?hw3Gquz1Jq^=+;_1R`fw!B< zfP`!>bQ+Me3Pt^32NQDt=SH$BW&*=&2!GN=4%K%`uWg^^Q=ec#GD zs^xh@%0!?-9%*2m^Ycp6DR%nC7bZ=S*uurU6rilI9Yj<-*iLUt22L%6{HxGRLI23L zqt_hs9U11*ej|9xeBcgjRvg&g*uLZHN#*9FXP1%K&2x9TXNGRq!|%Sl5Uf5?L{Cie z1_a5@t#@CK0x(WsbVX`vrgzrs#Vj=#LV7Y9i4^Uo4F*++Z>d>2F^$77dTL&>ST1`i zn}%B{hYYZ>k_teu)Qg85_NCeoztX(X&9N$!-sVTQbBA7cw9{?#rFcSnMd?vN< zta%=KKlsu@XNOsmH*701CFEJq$J;L&5lYf}bp_xQbepQa&zxUNqDOz)rP{+*>VvFt zW>o3joo*DXz@t)mIrxmj?LJo(T8mTeoh5YV6nuk5t)p&)XTNEl?BtR8xzVF-o-r49 z%C*{sJ1dz6Kuaio29U~GcjNmecHLI9sqWVd+D|<9{EXLoUjFmc&id!>_hmFEii8GQ zH>*ZwxvC`~{o^XRpQS7E^RtSd#!Y&ivEKHmZpmE!g~7O@>t})2Yxmszf@}M7B8)v{ z?jq+U6j`&x_~7zW?NI8X+fnU_;%lc~54^43uAN&{O2e)7ORnk~?rYF~@kdi7)AM6v zz!fbspY>rtA#d58wjlov{fYr8tz2=7?#Yi`M=8Cut-j|PA|IGz`1Ho<^`!+5XM_EU zy}!c9x!flhpRQdFBPPCrseSJok0DEhuEFPFOQDkcrHz@ZWjG-lj1*63JM1i%e}{bq z(>oc>5kdLJJ%Gt{2$eZO6N@uN9jF{F*zUq(qE$BDa!ph&cwZ#03yb|xeH-+{=iq@*D``gnrh9l~dD6|DP`7+*V_o$c_WU=H} z*Dg%bKzNAcq~LK#fjZM8xtQ7Se}6Yqxj3QH@_Lm=)O2qH z%^9M24gPZ*NPc4eQ}I{g-Q1GPBthx|;WgKW3so>%v{Dx-c4Pqp`YY`u z;n*G2oi@uAfV7!=f|#Q0uyaKLK`p>*^@b=2CQ^tH>n_ATy=*A~SS;x%(Jl_W|J5r7 zeL=4k{vG1y`W?I41Ac5QR%)u4ukk0x`JT6FsN<60LLbFY%Ocp+O}Pn!`}NO4zj|~U zfMyvbZwF($I03mmur46xeq;<@Bp=zMrJgqf7K^FctusrkFHC`Hb$5Ttyf5Sr36&ESXN@`9qkI*iOHJ0Kzi}L zFt_IfRNbmWc0L3I!LfO&=8uQ3J*YBrQ41#y&GncXGv|?-0fjYC1cj(;KuIlbJmepK zYD-x9?9a|Fk-58nmXhRy28I0NSv9a29IN?bb%mQts+*0)iI@XwZ)YA|h4n@_ieqVH z`h)?vVFkNT;(6jP5Im9sXF!}H#x5f6&tpeJ2aamJJk}SPRUT}tcW#DewiyNSpdOk=RXYlyPe-z_>Vu4er9G9R45ACY5?FZuv+_e4VJldYY@j|7U}}}(Bs$641^p-!0|P7?R9PJHcndg~2heP>aQGkE*->;>e5Q8S~tSbqSNP^Oe(JPM*&^eSDp zLXm8LCe*XoqG5DxAPotXF&@yNQ{7GZw0M$cCRW#?q2wwqPx?ZHaa%dp(y8r24E{Bq zy3lK z*9c`k4PA(4_W$y%-|NwKJxn@e`roq#-b-LSLBKZ zxB)ghmIvnTracptEmrJL?txFnyC*OQ*ePP#CzVn+%N{YG(KNH-O!9@b8dt&6+RH+4`sE{eZfP04^;5}PS1evs zFx$kR4wur1Gs(}H=sd}4cXlcY%Vfr+fw-Cw-wdtnlm`sV>f2v$_FL*<}>r-9X@Z5ESz zmxAc4umz7~g2itU%UhbT%JN+*c9jgswlhNAkWJyR&D5+G9Eb#V4*)FE`xJF&?J)(b z69rn79z8*-BcGo7kp`9XNm{Nd8>!t-6*Ow@&=6u;ewRyb=s~pC29#RToLs1UAtO&B zAsA$jVWkr}(61No*BFv{NXsIL0CGy~)a@sj)cYX<#9E(@t}f<7i}MGYgdIh?Qjl^q_fYE0k($nm$aWy((RwDI&1f`c96d8@RU0E4ewHN$ki1 zW!q6HguW(j=;?-=smwn7G%z0MZtoJsDsG^yRwQ4ybP7k%BUj5izq_J(j64TDnBq4G z-uLn4BjN|1^6QU5!%@#B#X>4=M#!_p zS)zGLh%uLl8ot&(!@xqj$=J5?Ug={FbWgOT@yv0)i)}?i9>LQiR4i`K%`Nt6YrS`O^%4e zvW_W{8G7v~gz{QH4=OkArjeo5fuEjE2uA*#Bg}(qy&wBXhtXr<)y=b;lw(>E{WNqd zc1?)E-^jiwcXu8)T4S0N)4b_*$=h#V>BtVPTRxRvK)a47P1hf}dseRP(KR~+m0|x) zD)cUXtY}iX@vIbRX1>`XL(}6g06Mt0TI(sM_Y7G5N+D5vRs1w$d8OJw+SH$>C&?sH zlT4){*dD#IN-=Sd94G{$?MVD3oceENgGE7 z2AAP;Lez$wPhp5xQ!R;y(w)W`sWo}+?iY_#bS zT#E*hm^E7NfgMaAo{zuLCnjH~MH8vK(+%U{Zfdqh$3H)iz8!GENXiT(cU-|JKFQRk zYoQR=#&S`7;pXJxOX6=ciJU07B3zoag5YOf2h55pCev-Uet_r}x=c>o&VjIX2Q@-{ zYqTH|SI2kANX?1s?K_8i4vb&qKk~OQKe3QUFO;{&yH{+Q?QI+W;v2!B1 zd{+btJ)(*%SgGh4x&Henw%5(=74&7?f;FUaG;kxNHHdw{=Ui4ec?8qtFI4+&K5#?W zsI}%Eyi57ox2>>|p*)H>_vJFal=+fr7Sy7p7A#H`tq{iYXevDi*r?xj@eEN{JzTsL zb+VQU33dc%7sA*<(W*EvNK8&dxUnVc$;_!Ng#5YNlD>Vh&{nqxU!Cn;$o4KO4!%-Y z@~mqY1Yh-`3sxa-(=<~^v@Qh)UT^K26%V`R}7)+ZlSu`AolO!%37qET1z*G~19x7wQm(WVX% zy|%~28?(n;9^Xnj)Dw0~)+2fJ)q<+!fp3=HU3*ftnJ#6{tj~J7-x7OJdt?8n$d*Pb@rulHFP%<^zP* zWj3xIZHTu8zhIT)%C!5o$~kI+M?|bOexS-&(Fl$OM({J)npieO{5AoYp{GVn(uc-h zUF$CqKZ*;PL&;0>?#3faY&BqkV95RI)S}?3>jZ&h7fQk)wJ0{Xl8x;p6V6z*%(N=n z5Kf1*kq0LV_dL`zbQ@wACUq34e>M!W+&@o#54|HCes5}aT0j|Mykx|ava{bm@h;se zgtN9;l_Pr;%Ru8Qn|blLbcJe999S4gc4STgiTvA@iWtPp2E zr)>?vUpr?UnGA|k+^mC?p@d>$15IV17A26Tp&cAq{%_k0Zt3Q{UM_DnR~S^kMvn-& zA%k)Q`s~MpMR#8{MZwq|vF*Cy5fo=SLm{}X`Itp<*Mnr+CfA!GNU5!2Z%a3YP>z_&Pg#|q zL$?{qj`I~v>8Z}*Ehc!bYO8)uk_A9Y5M}@kx@M?LC z>Df1MlkUz(f$Ced%nJSjpIxLPvv9*B?L1LW!K4Qpv<#O<%?gqb=;)4hZKtGdVN@7^bNugyKvFxt(%8pp}-k~fo>Zm?BD?F}8 zix(;#H%H|95eja0pgweoN0cbF|D)t^HD!ny2d*z~opH`8V@p<8(H}*Y>8cMl19fZs zNMVcrW3%EfywV;>E}_eO>NZxyt2L9YFX&obiKemgcz62=)Uf(z zC+j%vNMX7Z`3`S46HN==LUR+b0?8dx;Fh*)koS$42!OLqoLAr8YfLzGeHgn^J~Qjw z#=!fYWGXo4hvt``SQ3+I9BSW#tA<er9owU0@W#*q38}2 zRiQzpn1h@pNZa*APzs40{PR2wF{e2Ql%+1SB_rFl*wQo*eUZQuQ{KsAd4H%Bmu$yz zQqYWZAt62@SgEBd1k`RRR$9^sAe|!m8b1nINEKDrZ%yBUkC*fO$y{`1%BTB#ch6GbbOYo;FeUg>~S+^;%8ko#N{Kd|0nxoDd?57YneMXf?YKV5R0LmqNW3 z4pN&jZsUD*iYv!jZdM0gk1Nwg|H>8=?&axU@pW3Ab-TuHuACs%h_Y<8PqWojraONgJYD~K$|YV#+HMFkzfO3h*l z48+Cs;T_ubz-+W=2dq~QEO{=))Lljdl_8l$RU{|#nKBwqHuMcWSV0$C0F4v}+kEvV z)_$x44*G)*MUz0&@d!_J@`$R=)XRHl{T7h99PF^&Z##Q$0$?+e4pT{XiH41M`u|@P zoqIgf@B7EcoRdRQTg|Bnqk}oMVNT_I80M5Dr!XNi$4O36tvMgk(kwP-q6o<+grOW7 zNk}r8Idwov^8LMkfA{DgWA}Z(uIKA{P0eoT#2A&@1S{O0e6&|X=^bQkmjBp8Sc0J| z2uV9KA81FX`4*81S}~b#B+4deODNvQ}(L3Q`AE1u5X3gJdf0g`nGN& z><;>1?(bu~aC+)OUs)#2k|r4Z-T1CG=Z7EndqcQ$brF0CcDAYEHnu(Qk_aPnKklQo zpLQ!n;dRKXCB*9*71G6$$A*7#5!mZYuL(t|E7)Tc#Yh+V$5{gAT(8rloIjWUgehlyEC!@3AG~HRl&ne0 z_7sj-Ls!eYMN?pYy3=irs6oTspV%ur`$0Kgn?k0B*g_VX3Hw#vqNY+@d@HC0!bJZn zuLl9yIwi$+B7wa_&joSkN{(Wxpj%}rNRoUi1GX(IPnaw?oR*EX2`(~*?k1^c`8NuI zD@jCtbN9mHYH>yy&k21|R^(Iel4TfBzLX8o{2G4+$e9n9YKPFY=Njss0n&=bT{joz z#AKcK>sa5rsHFn&v~{PVe_sYRLLB3m!o)Hw<9a2o&VMi2=RUMtl(X1^@8TBy;m=BL z^yaq^CU(WJcCie({`d;3+rr-~8kNWIDDLz@pcS_^K*!9G4&Wywyy8M}8a&(6VT+;A zpU>;ZR6!V0e4{c^dw5Hsoa%)X5d!cdEeF$@rMDQ%qXO(vT+&) zOA)h~YOq+k1WrF1rcG<`-V^46ETDbynTdPc)EJh+n9S|Q? zA-v^aOqBvtMF%?LM600v+f7#2LeAYv>9`|wP=(+i;Qtx;9@gnqT(ya3g3&Bbk-_C) z+1_Eb70^~WRHjpSi*Dwh_0kzga(R~5_glaqk@62@@8&4ED%q~h$^7a2m~XTpD!J$?MjN${RGzSae3z zS=s1b_r8rK$A!`Fk_*IkrOdYH{|RPqyw6xuIA3zJpy-S8nr(egj}`7Icd0_x(Z}2Sg>LaevWK7;*_t^4R#)eYdbT1bz z72MaJ^0*VIc!s$9zAd*)QGUNLTlTfE!A(bO$oTWz8~=F(&2C2 zs#Kc~thI)Rk4TuFC=Js<{dx9>aM27u#Ijph!|syUB|wUwyK35yCUmYMLM?Qg35D(f zjje^^gWanZnsJr8KF-o5Vuue;Y3J_5k9r185U?z+J-oEC-swab7n80C#%$Wok`mRR zqmwCHN3)ud-0Ayt`GPry!~{P-as$u!1ypn((5kzm}5uNk96| zuKH;W{FH9kvr+Jtiuee{d%*bkFi{q~^Efu*z$GLMGAavz@P$PUOnShz1BX=;+Z zy%(&SW{QS0Rc(ZnAm!uR%u%lCJP;wIVP1^4ZB>+TJI`Y4`A_vsQMOj+D()@KM|F4a zz1rQjKmOHdYEONo{kS{qZ=wct&*Zkel=Pl1G)X1uH7rBiLt<;QD2z;`fp)6ojJP`_ z@apH?iRT7#F2Su*Gd-&>=A6D7KKwBQn*TLR-w$kC`a9K+T)k|5YxGQU*Ii|gZg{w` zVvs^!66gKBx(n}C4xvBZeRYF>>v%i-J6a+An*6`FWxHBg#1HjnN#P077Lgieecdv$ zC@xd+ZzW(|p>2r>q07NzODQZlo~5aYXbQ{Ibdt7m$ikIyqFPZ?Kxk(v|CJ3$Sf_m{ zAHwW5#7R|_IQ#SGqbk8BAf}uU9@Nc*Lg?o^(UmFe;@UZe%s@cakgw~MK+4^-G?GYsPX??T*&CdX) zzfr4Q#$4QZz~_d42+Je64)hO|a^{4k^>QlM_4%7+q6G;43aQL+O#6wlnI9ntmr%YTX|#f z=fv4TC7gWAn*}W2d9v9e;J+cUrPt7p!7yyA&KxFQeuBYy^~D+pJ2D!(e=+5r0qOYU zeGHLJ^$T`1VT@P;SBZo%{jG)KIyKgb`_B>WtQP1}v5wlJJP-(_VwP2N`$V3o*eHdS z6S_u#Qt&A?)o=sg|FFU1@HE@;Qj!2T?VF9HOfm(wX+ba%La$r1bQr%FeIOMrecZD@ zIMXc-)j3H_2w}MUFBm>em1Lq815*wj$ikEUshvn00REOz$avIFlfi!ZhbZ=@MxI4U!=P_~2GjATr^41@-9I#a8rtqvv1X9775H ztm3NUI#KROmg4L=y-BN&jiRu{d6L+@%dImqks#|#N@#aX3eANN_*Pe7eJ>kHdiDw2 z_SWcNRh#+~lVH;K`Vo9#&7*Lj_EQsehz?Uya&-ym5^N*|wtXm>w>>P5rb zHo7@F^q9g81Cn-!gFVJXRPM8LqIkoI3ciU1M`IgpOXZ(xAPlMxIxJ`Ui|%;BS{jac zZt};`fe&I-GH%Jv5tk^SkKO8`9PZOUIXe?6JmlapA0fJ5Fw31wj;{cx$g~SR99Brz zvbGR~R=&_s+933+>#j-KBw^H+&(GGJL^k}J;)+XdGVzB3PF^~gMRaZ!>&??5&OHlv zy)`9fVZg_3U-~N8z`7t4xHTKvz@Z5@R;% z`gI~7FJTd(O)Y%%9ULiaBW~Yz=EneRf)x;4V;YG;{0zq$_31cqIl-#2q%o`KdU2x> z2c0!LjEj$EeyVwUdPWuAqOKqOuHHW86v&FlBJqtnG|wlG&1I^m(1I0#*r@t$hZtc-=210J3PCYWSqdeaeqicwKTt_jJuXwzM4zKz zgXdwLfKR&%w#m*J7>10Vc+{F|&0DqLTOZcaJKm)*ng6?bYEW*OgTdc+(k|_Jm_jR9 zFdo5+Yy;6WX^BD{U&dqY*qly~oc5{>7OE4W|Ks-~K(S;N+8}gJ$u?c+@G#Vn4SWKgfN|gh-8Wfni!M=7Ab|&s zv+50W?yzbHO~YSadUZ>qq^!f!a{DS-*~w$EazbS&-E4KnZ0^(Q@&i z@6+W!>V2pBuT>Atn*I84$W&GGxJ+n_;{1dqt);qtBcW{r;#+ao-PrNx{t{k!^-8D!54vb#~ z#Nr^BmCLojL$1mt2wlww&q6$CvSQh!nu88mh+>GirfKb&$(q4PoI!!~T8IjJwn}C0 z7GWCU5C59!+U}8dh}^}kKvm0c>6|i%sllSJLLDvQbo-nmTFPRbZ+(lgm%^jCF$uq_ zDW)c86_x+KgS|P17JHR|8ivotKaK>F_-5z#nVaV-UMs&SXmY%D#tKy?S68h zA&!K(l*b&j9HJt5E~DVNTh2I?s!6bU@(d;BAhHOa@XHbZml#5Mor4WWv@MQjH?3QV zDvr6nmPvaOg8MK@@h5|Ts@AF{_{oWa6slm1FwDm}I&>kc-DoRjm7N@FCWO*?nfA>> zi1=sRYH-!WOA@ucZf#?65HiSOY96h`Uh&i(wXx%T0Ok>%0>HG{UzqH*=-^TYxL6jC+TKXXH%BiUN9dY zk1DcfE>v(+2UN@fw|EK2LNSRe^!2@(w?SX!i|bZGMOQF4e<)P^?8j^1*=q5&>g zH{?Cdpz!C!gOr{I^r!L7+IBs+tB=BGF?D$YXmV&Rsa$PfS3^9htM-widl;sv{b2A_ z^NaU~#1kZ6mOd05oouTkdY%k?hm5t(M9D}1A+o}%>3mcTqy*PQz3v%FiLDTqOU>?_ zti9UGHP#?*)ry1nDq${xh87n|yKc_*&#ZI`?}RPNhz0@mIU)OA{TH9n~k>&b@oslb^N|eL*2eRXML56QV1C+}f_C#Ru;-b%(#4 zKURIB(XXA?-4JiCp%c|(|4GYH2Bv9{5mza-7XezQQV?!#TH+Jwmz1+CJC8*lb#A<9 z+jf2gYePL6wjwEvv98vu)6%vCaMzIa7d`Kw*tZEgRh2?>8HFlEi&eG~mU7i^+tL5j zA>7Ot5yUZuya@>uMp5@Kd?F`6zxYyMKQ!>AXDIV|)rm4y2bxRq`7HOZrg&$_ab zu6Q~!7R7I>q>RgTs`;Akazn=cqSe|w>u{S|C*_yPXJ}o5 zMFpOvKq*k|yqS?q_-36W*@*y+X|jwRwg>?AdR734nuF$2L@c4@GUZf*SYT#^sp<95 z_?_h0fR-cTl-~MdvUyIJyCPew9wfit`GEBV|Q{&=YE$MriKq2ahvY?5Qg zwUUX)KchvHDgBh#GWns|l;2?T=f<4+cGJv`)-bSg*8JaqCtqD|nB_IL&@O_JZrQ1# z0|r@yjYUZxjmuGigm=xpt*Y=!fF|22f5J}LkE>Pl*PBbg6>NA_udbRpk|RIbFPg;A=>cs?S(%XQF1lo{3Z}%&q_l(E?O~B1Mw*oe*n`biFLZky(Y0 zj=wZkTe0+R2{|->%jtKnO~KznH@SP>pOzKa`A^vQn;P;9;-I{)iVl(8EhcUhQ++X3 z2_me6X+C<{;?$iXYv1H}`kh5#aVxo+_FGERdL`RJh6#MDQKI$zHI z>MAE+b=TXfR`yA8z#6d|gK#qy53S3j6^85ZHEvj`reTZT2V7=wz*V{>cmr?M3pE-a z3w(3?VL`%;vNsVIZpnx6L0az}kJR3IhC6>^K(h@LyIqg)KJ(!OliH42q?MB;Q5>dX zSZ^|M)d3FOZ<%;7sN6e~ztgt$|K3F_bEi|tl9F-K_BOL0lcau-kH92+ctw(w6B0!I zus6&mxgo5Cu{I{6+)g#9Ov1R-cuE&bC#_Og<`-_tISft~YfBUU4{_5GT@HnCbsn0) zHh(+I@7}RAbYABe*Q-GWzL^Nm$WM5jfq+{eUGq`QZh>8A*gWpULL^p)9?j?{QrNVK z?vzEphiT+!mG~V1W!QE0iD8Z;I8lOH>j7?33KQ&ILiTc&WFm!aJRK!32Wr@bzG!59!yhU6;gNM^IwAt(3Afjc=)Z9cN;43R7+ClW>RwrzMQPjzG=^KAhk% zF>$OGKjnT-RPi$3zmTsFE`No3N0Q{k#EZ)*MMDv3kmyemNma7Qs zw22?o0_2A)W-~(gPr8ww_$fOnWJxyZNd&~F3jM2^bN}tY=y@LY;Lo3ewq9={3rggx zDi0l1ewv#2yH>phh&=v7IA6Ft8?7^Mu1>I)Acn0$xJ)qwkeBj7>+Np)1g%>9NE_C) z;$tz5MLrSEC#Hul+Usri`io04U2>IkVEgg){CD`e_RN*0E3~1YjDhQB8ltA1AL~L+ zKGhP4G#`;k8;@Y5Lz-qaCGEC`gNvp6$099%v-NALV232IExv1^Q3=;_7`|~4diw>e zyKc_Xcdvxx$AwmP3*}hEeiz+(JQE<=`SC!tC<{x1XFf>qpR2d&C^WrNNebzo;{6f3 ze;ir8d^XS3p??;_6?*LYDcRcVrY?+#J>GU8rF5tc8rv_bpcgMI+HbS`v4Y0PO^-1;x$mg}i@}fg2d)@|^obL3;5p2@P*|<+`gQWuJzEfA*!i9Q-s&YC6Kn zOTxJwQ~aEmBA*<^P_Iqyto1OhtS+eOTW_1gRBM{Tfw0~Uy=re5p@BP-%3a1+(##P{ zIf;037byWpidLvM*ju2$e5gJ-kJMJs|J2s0l8Qu=uJ(S>`6z}el*t198WB|DP}o9K zw||sF0h6pIUei)WVqSlnE`_FV?UDeY+0S4;(-8-RwuwNr4#=K=1*}Mokgl%*nP9P_38$ z#Iu=qn!Mrz>>}4UNEXgLwE1EC zfCkiMW4NnsZMIp@UX5CG!T#D|t#7V=VqCdr|B`GzXIKSfm`2Lf-EriPh?h-%5v7;l z@d@pxsdunk;fl@a?E_KyLYkJ<(7i-Jm&YUHFBU&<)z-B~*PT5EbhO@PW|i*&|1g>x z#~UW8UoKuyY-6=TcR2N~?H$jkv!ag=mEU+-HL!bl>@RyU24Sxf|36THOWKUi_t{8P z?fvJ&SEEnYCVT3si!59E|K6^t&}P9VV^%WT8|nt$n#RM9MTozd$tLCd8Xk(1$cSfE|kp25p^SIJgUB6|{j%CmWEqID~ztP@ya|vr$B6#~=>(nHmXt z$JtzB)-F5eliTfE55EcEw!rf$vy55@A<Wc^gZ?Q@Dt)Oh9bY*qLlwm*a(YZmp*N;@Ao zCLCDdTfO~<*G>C{I}tqVZ93?XOcqf60IZ;vp8Q`Z@)Pn{()lrh6+o{T9O#c@z;)#3 zDpE>4L0%>1|3nju_3Ddy_u9(v6!~BPVwvW$v zqXp4=f`+2U9xoYx5ttu-@HD8WfIv3wM||p7DozuSAXo#H1SSM{kdG+=x*z6P&FFSv@PN%ULl9m{()3b2c%GfiWBU3!M4m5=(?*r2X{zo&pgLHe! z%rYP|kUM`ai*t}A#vqws5M_UX;pZ3OG zmEW3wNe)H9{3^j?I4AVt+VJHwY>_ZGUYXV#6)Zfxo97lDes!im47Kopaa&K2@U!k# z2J6OI1@0uH?QW|ecL^%iiJe!c*O3bv0w9#{mWna)a+;>f`GbSI&ZfSnu71j4_{g#3 zI<~5Pag{6JrGqV?*>X6FyZiobxOW^>N}o98zga1=9E4bHuMIc+ohI@;1Bx~zS4I|} zl{ioMnT#I2&cpGZTAzNZvg77#Dk8J}Eo~f#gq%mO7M)$v#LS2RWdE^8?^3Gpt%uiM zWO|3K$UdhOc6D*af!M%W=kL>xNAjOz;Htas_TgE%hr^7PQ&u>YKezW?mhz&%UW&m8 zS@O&(tMsQsBJ(Z`tu>^35K=WmkRmEC26J@{hzDx^%->w^;5P0m?05S75oc68Ln2I9 zT^`2`sJ9Z(O_3m58XA-Ni*^)D##t@EPV~J%;l0w>V5MDgPFWcR7SC zM1q0r`t`>kuch4k0F0H>U{o+D_tX4*45Wm$I3-To3=H zfpxEEH#+2Uyk_ofisw(rA9RaXD0J!%>AHiQ?FBlMW^1Z#yY7bVw8{%!Zt3QCKc%SK zd$c~knnQg$u1@)LbBbYoFIwQHOd+bWP5?2i8JmdThST z-@9(lIyZ7D26|f7hXB7vUayY}KJx7>s0Jfwk@M}8t>(#&@r4%G`N6c=V_zNY)x=fHQNy0KiIVJJmD0{g}-5;WEQh5 zZ#+$I)v^r<6U^TGeAPh}gApJ=(|)f%X)t`>Udy&l2pH8nRyh$=)JOPPFe=qdV1 zEFleD3A8v&y5%RNSJ0I{OKl^ac%z*VXYG6o<41x@oj}^iVV;@W@=I>J4fI_Rc#&bg z2svV|g??aWIoVMS)CYdNkir`q>#UM0Ud=aw@~|9?HIvgKFdHm~30`_M3z$Mo)=duf z2Y1VSAxkp(A`PRN@)K=aOwjmo-((@lB$Agu%sIW1k1W#m)}JXS=@~DR9J9wu@0VBG zsVw|vB?xYt^{+ReL;(b88%M6HKUlU)ve#LV!+#&-oNNS`J47H1@JtS(*I5FX)Pg`H zM^b9ScoSKl>>Fuh=}_>Jk23x+7huM*3XedluXHM>2qqk$s5D*Wo0VAoIV1Q$7FTEQ zScvj-MWh+0-42Pno083THLTLpMuGnW89%Zt z^SqvSao~R-cOX_%xbjB#oh9T}_;D9;ZrW7z<5~mAkafCaNb#TiyiU_9r<740RvtpQoTH+CK}i{XKsBE6?ORP z?K6`qHG?6hhVB7T)sTqWD{(c?mVbsVs_hNiTFuc;KPN=?m~eI7?B8_pE_?05p5!rO zNz&xrj;5k%9PC{|_{VQvo8)CuRL!PFaj2m7n^VZ#-|s*APEBud)jEad{}eHBLLbNBaN72< z5evNr?YTOO^o$PziRw=L|M7E-3$G5UY-E;jWbsmULsEw#Nb_%XmO|ShHcy^ z;Pa5(S#`MYMP(^Ms8@6*Rp6$nU+eVyqsI z?-mDXtUFr=zk1!TpWtkIpx@yVW%q~YNrR8M!`Px9%8tF_V_g%OecH;@j~cMO53$hE z$9-qN46DJ&4p#JvUfu^CDZm8ISsgyBGuW;m-;-6qfQ<>M$@P<+i77UwqfS&4W3bl=QGIIiv+SSRmNueoL{lyqSK5=qrHm=gCn7}Ts%OWs zP3T=mr12>>8Afui3nHVO?bl~Sk6HuQHq!y(Sc>O^)i}%M#WeknaxD`{B;I;#e$JWvyK)f zOQl)G4E_i1QfC2gxi{_bbio%$px^0$9_5p*W+5r zR$;6ntLvJ1#@|YkJWI}NNEaz{45`_HGojqLsXh;8jGm!#&`wz9$93RzmW{jA$QRc= z%CQRF31t4f{G!R&bNpk;tII7P^CtH%WI_d!<5-m;Eiz3k2qYZSUN7@hIg#DFuk&r~ zr&bK-N9EOLS{_A@*lIdoCu$xmc!oN@c>44agI^1?>ZJ1>60Qne)3{_aHoVsd2dQ(2 zttQ6(%psZa>wX2bZh4eg^zwQsJkPrJu0K3TI)5ZyZgni|A5cb;SRg5X9BfGt~8DWWbsyA()2 zk%4P-y>vFWZQj2g-`_c~)KPurDlzqCJ5(%8GLL>P61BI|6}r`@l)a=%$Kc~kC&cCu z^%6Fjw!YRQT8QFpneScuF1Ls&ZUIjk$0v)E^z$BM*`FADJw8qO#q3@_cn;=#Dq_&k zF^*>fq4Q%sMa5&w!N5$K5=(bK7Pp5tk*l^ESOR7}!UU37kV=VVh$E^(;|_==Q_O+< zLs$w^MV8G$O3UUd4)K*=?(8rQP|vsBMsuimfkj%2A_Svtp+BZU;Y}C#w;-UaTXb>x zW)?xh(rGeT+ks_j0`BB*d(^15415WdU+3DHMd^se%%$dsTiW9gs$paOy=y)u3$-6T4KzoDS1+F|%+MUah9X@p#A8kuVS&=SI^X^` z9-I4Pqnl-1i>K|BS`#wiwc@n-l|lNJp_>sqwsYiFt<%?5_14GTmp>jixO;jkBcNXb znVZ$p`6UMXbfoy-e1!Ecmcqb$jBin*>v!!Yv!D;JwreKOVJj~~UBb`5ZXjjHWdutAcXINSpYTq{Xc^_hgEek~$Id5` z^_2&gCOQV`n;z`n=|UGAkvsn6$3~rTU2DjGOh(e9YcO3)Hp_5RO#0*O3ew4%a9whD z&?)hr`*FQ;!kHUyZu{~|#AFRD25cF2)@N2g>2n>4N9ihmBKGO%mb`dl00p8a%6y=7l{nNidT*y z7Wn~&XVQCB!52ZfZjil?q3NTZ=M<+7EG|Y0E4u5fjanRJ1-Mz+ikEOuBkD)a=N(Y6 zOL+g0A$mkM1wHzP=Q4Fa@hw(Wm$FcF+a7J>9*R3m7Zw1I9SbR1wm`Zaigks6{?hP# z?tkBmwqQ>z!@kwP-QZad7}{m|MJ$fZU(uel@yXhkf+aaZ>H*Vd5SSs&yH|shY}HgT zD?PHe;lbkWok6VVlbx@%q(G`w!#3BsFHYWQod0>#^UJL~@1SzEq5TU@L$Luy>;(DZ zdV$WL#Tx&a^1L?h9`Y|zO5wSM!3MYygWa+&D?$LY*12gYVf9xaT+wvZu zcPHm)j~ykr)isYjoo_G})GQEh+durM$X#`oo}-!!N9#mXSh!CYoF&D4_SECZ?>E<- zQ+iC8yAMvAE1jvd2?rR(!+*9I^T(2Gu6q}NX8CL>PrSD}9n`=89*G^vDp(^}1AR$V z!*_F!(#(Kz?x~}PSFMEW4Zu3m>*lFnR^s~3QIqV(3IDI=o`t>3_HJGy3_~zLuf@gz zD>MJ!RtK;lq~B+$1h4=AfPjq0@#E74F#g02cJ6jLbgK`k8s<1o5!2LXrvN36c_~DC zFQD2XI%uT)cII1AlkH`NfcgyN{yO{o50q;H*h?&RI;-F_RFFd@fcH#*fchEqn>|<} zN$lOzJ4KMc{nd)#`mp68=pg1_ZJf3kwf6Y#X@7H7kW)Zvm*ZLnp z``wz>*}dZhGVOV1h&DpkPF#_isoZT_%pcp5b+{t!5SOL);opKi>dT7Jtv7OJnDD4L zMquXAQ{5&T_L0sjAM&!Pi&b0L`+r=as)u|Zea!xAsaqEjnedDn&p6tx@N(_y`!yxh zwOgw1;`d!2#y=@CE2=W}-IT}r*S)J!rR4=;PF4u*~u#J`1|_)bwh7X z9ggx(1_P$mQJ#J3`bCbv5}*qg$WNQtzgRJ7#49?TZr5Gr<6xa5&s}Zi&VJCDtGtT3 z80 z+M8hC8Cid5Ww_{~w81Bm zwe%AatdcQ+>-UH~CM@${I#Qd8>r(}Z%LgBm`e8-FWn-!(!-FBk+jKr#vJ;tqAqW!; zuR!$rr|m8Cr--0N>s6tZ@@n749Qi?Nn5u6M#<4mcXLPa@ye(?h%dcn|#qrB8&txdx-VtF^pODO;FpRbF*&iydiW?JX)`wcMYLtPo@TCx~i zr@q6XLcDk3ZDCgYAj6-DD;*&NeE$|wQ4NNd6}+)>_?u(cq{(`m#X&pX;-q_p^{#ke z&GV;Su&hp@Yr^YL&Mr>8&ZQMK09{|l7OBao3}4hmTU~bsTHio%vZnmA6-O|edy$Q$ ziRvD<-vI2@%Wdzj{twh*CHgvtK;gFjk@dE|hddRTkU#9I9fZmB?CfkTVviVHf(!hB zAGmwWd5$p9%`(kO(!Z^t8xUnie)hpn8_80k2FkbCSo5-xEMeNjpL;I0pMzJ){`Qm4 z?COmE`j5-7ie(k_tWdgV0&7y}<9{iCU1J{#9Ev<>##DGbFJ|dONEPV|LM(gX8LV&J zaAO&xb=J8L1Aa+1F5GFQ3hCE~Z7$rl6dIl=Q_Rb5{N$WWTyML zg=km!$1^U2r>Wp-D(9amnq<5<6Iq(Vnb6-y{*!IrQd4ZG-+_w_7;Y(i1nx{+Y6}eC)@! zVUPaX`mH4Hu2ty6wWqP1^}6iJDo;R{kh|j!=Wh0q&q<0268uMHk8~aUy$9NSCl1`*SUTO<*Qn->i8K-4Q@dkPn!x z`+qO%0y(o&?E8-JIao2^75E+sKPfQh;5Xa#G^(Q-iX+oyf?}{dwJmi#z@J;>0BPs) z8h%QEE7RGJ7uM-q=9>u2|IU=t$4T90o;>?Rrt*&?7!sfm5|U?GMCevkj70&q{+wSZ zlwr``zk?>dwX_W8^w<7hD#Gfv?YG8?Nr2k?pNL+b>6Dl&H&!Ky$2^-zL78<91^DKB9=+5{ z40)V$NVI>WH%j+p)7d-{S2nMxqTx~Do2t(VpG0e)-!eeWgKFXp|G%#`8E`h01yk2F zF1*-M8k+Z%`}IzwP&^9!=fef{OE^(>=bL**$h2*vLM^X^dAB6x?Rlc@lAsx}gye2k zMbyVruSN2)j3!>;SAi1|9}X-v#G>!~?R}r%a<=xkF&;R~W{nivpTBEpZX5cS$9umB zJcgY`x>xkYxQ0DKk@y?0ldXsCDxu*nc+|Bc-U($l*UdhNzZJ4~R~Fx-1{H%&kN;q- zNa)-*8~4iGe@#v*(MzLALhHWU0vE&34ij+NI&S@9c;2bz&zjI>{DrEuAuK4c%D9+* z1efM?TOfb@M^*Ga7o7PY4*`&P+PJPgqkDcS$0j0T3e8)!Q?mN|n$~itnrLMSB7LZ19cMpN+N8q1z{S-?zDM51aHPuQY7cW|ke$q*QNC@RCB^`E}?6uJ<$}FA?vpzKQDl#vCXIe%_E(o$qctm0(EvGo9J8dDBv&h;I&$sjvtpTiESSqLpnwMHSL^?o9PM6_gr z_-vzujV6+5^zlZljV7>qRL%j|f22K^oiv$ZeoF}!rBlr1eZx+RERKPOk+VL4)#n`< z$*KpbfK={7%fUul{;)Crt;(1a4`+Bbr07+X46f0{nz(`|uu*74(_l;>@{EWtRSr!2 z43*(3oV6>pxuAIVErX_M+HdqE|usK9neDf<4CinuQI>@TTm6LvLDXA))gLIQ}p9q`P^S zo$bDQN_{DyR0;sw_nw=p#zJ9!6>y_lj<}de2TXOOFxsgk*>s!U-jl3_98qU|%za2u z%_iXvm9+{p&sbbBw7HJl6dmk4_jbf|HG47-2kAz0TWx&E*n;`Z0onZUC7wlZt&*Fd zwa}CEXIz3_=~9RP{`bgWf%>%I>eY&x$fs9rA02a6A8l#9QOqlGb$g!J4uWlx$y%3x zaYJ@SL*7~YOQ(z1(f!lxJuB*N4`VL`DId}=g1E|wqDI-bE$=OcOC+Le$L(A3R=;s$ z6qlo*LTj(ZXZ~P1f0>iDffmQvzP4VtcZ6=C6&a!J_TSL0yxyihvBy^NA_Fl0#;WO` zGWmEP$n#k)GqfykCoAx)>PGe@fK4OQ_is&D2$@;)rhZi~c4YD|rg{+E_yoj#{vn16 z0_$i!fSfd@RoiAm`8h}qIY+hfN})Ezyg76`cmUe1c(cX)`UxUso(nMyYzr~%{`hF3 zv^kS4tk7F2R2=9dLiqiQ83@%qe27nuc#+C{m(Pmy?;ro>iHH`QwUvGAXQF?&`^w`L z<3hhRaACgzhk2s?eD~75yR4>$sCK{W=df+3EUiWl?hEhza5QWjSkf4PZY8@`o$f3$?U59 zRU+-^sQ`8TjJ=hZfOcRVFmv%`p0)%i)a_B3A~)rg=u~+7uv67uz9IXXWUZ1`e@X~HFKDS;?Zm3L|Vwn z^u5V1jiQQawjoSuR}UWrrniDaS%<%%&VwbJ@IxUxC!j18EQ+ouKwDz0>5siO_MGd7 zz1I87-r9AZC-k8tv>kfd6_^m6pW1)`Zm+7*D;vf)my_MY&?q_Pum!wKgn&QGw6v6c znesMeaavnB7!wCPE!u!F-nV7^BFR~b=+I4I$gB0CVg{CS&bHdP$#re*Fo3JfnmA0% z@zs6yJu!~;`l^W`o3=ku-g1NwncK|(mNkw}Qb{G`Q~XIswENE52!k>I@CgCqjs0Az z_6JDcStt|CUzi-u2P1pUJ16Vo3W-}~J?)Sk8M^r29p*FupK&UZ3W4RRhAzRLh{)UG z5|+?vD{w2<(dtcm#3%iQic7N6SO~a^V?4xAcPU8)M{3(0g_u>zIuJX8XN~1QAuc|x zVWFJ{w-va5T>5tqOkb?0qw$DZKM1`FtXce^TYpC!r<{0qJl|PzvUnMmOw3)iuGbO# zkAV=4k>}RiNc#_wY`{{OdAJO$*@H3mY^IxkYKG-u z=XPpuoqb%u4YT@@GC{O4H-N67hXo1ah2luI*ZB&4S|)~-`xYulhaySOxBbAbFo z)dM#aYpyIzu;M-K8bLv&q-Xr)m%bsvt-oKm#_zCBq-RTKbfZ@Ab4edtEgXMpHz#?1 zbr{7xb$aQJ@R_N5Fh&2aWvc6`aq-3n*Ll7Y>e#aYr0~4{o5>ij+aRa!u2S)w;{KX{4SnT3nlD(~rOO zz~GTo8HLXO1gI=_53Drl{~^U zSB=TUJ4LwJJsnyxvTNMut(y==<{h)pi-DDCJM&eqHNC|s0psEXcz9s6|42`Jb<{>f zM$NTAZ8>cg6V8{LzGtti>{48izHOKW0VzR=k(;C_?dVQvMu&8RY&3|{;2fjV(K$*|n26Hd-69(xE&WB1 z-@Er;cs`%!d9M4u&ht1D){}O@lHSk6bv8_z!kl+%I!i-qwTVGnrD-g6OU_dA>ad#f zYI)v_0>szP+c*&rp5C&*_GG%*>F^+CqiWC}h?7unzo_vmNt4RY#gdnMk=+l+X;pOM zJa0y7i>f(ff|-0+2xK)6OzRv4=pMFg;t!4kS4P7`oiaWvho}2x>!nklLh$~hgOfam z%YI&R-Y=M>RQ|w0qZ^Yb5_w*mQ)af>$ewaLiSA`Gv8PJN(CYpp9p%vPBazm!C`?CI`>e2c--)r-q>cuI2QxW}3z}{La0^`1^y-=8JO7dqEBAp(QR{7=7xAY5z^qs0Kwu zcg8OA-w)Po{_>)kPt$2l83@_5SE9!9BIJsbXH|FefHVSyk{XHn|2FyvXG*)lEE1ii zzpX0Qnid5ssV3_r>n(OEpU4v&8O9A7LN6+-W6}lztOXuY3KqpI`ACcOg507~GC|ET z8VdQUn@7<=TshQfBz((*V(C4mj!~EFRFHve!WKpTmT?f6T!w z29z=qA6rGl^gSa`X+MoSYpqvRO17vLC?u2A zVZk6KrjYT}=i-6vVZCMRH#mPLh}2R)n6hb{X@!W9pXA@K-$I=K?8yo2P14RnuxGvR zPUND!v=*9LzKCXVoaD(Sr!Iy8i6{MYQ9 z4v(^Mw*&Kc6O0Z&naN2w_q2o!9GSynR7;;H##zZvgmRb&5nij(&ywbT zE>eoK!JqTBv-`c?$&D>+|SR51`9NVSVzETT39*%#eE_5 zqb;g*t`#ye&GLY0)KSEQ%%6(&FE>vZPHi>(^u?skP10zqwwhxpPw!7agwarV2Q$~( zzPzJyY557tsp$W-2`3ja3Vk!W{~Dnd2Be-S=Cj3%qD-{A`?;C_PWv@r$|l6&N_efF zn>;_pj5E)UT)({naH=EC?%tlq*cN6A`~Rw=xDH!^d%H!BcKey4Ak<~j>T{vLKDD^% z*sBjx8lh!tVj7-28y7_Wnj#qOkJPu}Ca>N}OyTi#B_HDwj!B@X*;gDM7=_N?a+f98 zhO#fT5-T!B8!24{^K{xQe`pnLCpbh#>jj zrYoC~Vl<&FOb(3Mgc=|~WcX|zcWWXW$BRq&F1hp|@#&tXpz_$Ud5WusBf;PbQ`Ww@=rEC5`^hRxWA6l2{DxQU^0_NbSKyW6z}nPL#~=1lqN%SxbZ)N`|6yLNI@=c zMh8ukWRtsn=FFnlV(HWgXW#`Mn_DNSv(h;4@%sZc-m&F62`aSm;M5@}SXdNmdLrN5 z&xXX~*84N9kx5hVP?iBjR_&kmo~v-ezqiJ8nu>L@pZc=8X7MQqH!G72t>eS8^ITe9^N z+R0ZMftZ|ZJI>Hy-n#zKs{jfraeEx`)Iv+OvN-EpwZwQMCE2rgjv;@|BJSL?>HWy- zRGDr^O1)D0&b0TA;9e8gPZF8&P)^ajm2wLm8D^7Gu>P6LGDwxT_qG^Ou$@pYJ9I9} z+apFJru0uxn(@P9kMFJz&k%usZ%sWerJMztX;IN+O2s2WTf8C}bwiwPsXNf5K5C}* zN&Qya%}@=8jS=$kqx6~5Ct`0H#MA!Kf@|o9EFM1#iW=JM_kYRa9=PH+7j5lPqN2sj z-aNT&M8RQpBc2w*zW)z>?kaRWA%ZzEtLL%c5@s!0gVFlQ^W$YP3q65ruZ7koTcgU? z2yOU>hx-+*xyYX>d*3^?y7zs2<7jChM)WR5()h1PWA0-mW+`Zae(1P$Md?FbtmR0U zJEExrf^cZgYkkyQG?qYe_E2r239w0^LBW2ik9^I4Y&rzkysi&f7OysU&z!h6A9VQ7 z2`T6VvtW`n;K+pN%xGEg8)`ZrJr!H&dBaoFRdchZBSGRY{M!2Pn_F_7lGCod zU|?c9v#}q!vgz2^O0qHP(Pk6Vu~rR-eFjlj-lRHk>?ut7PTl%Lo(R?3kx;<7%~V!` zH@0pXq)nw2j1pkxx{w&nmskBDjCYkOm395>Ak`O>e`pu=!6B_~LVwz-U*NWmdAMD{ zdE~@Nh=)m#*$KS$iIG8!QBeEv!Jd^W%Y@9So;P}E_fK6!>>K}lN0-KjO(TWRV!Z)0 zo&)#dhT`$wFBwabH|$>S-%XvzDlqvgyc?vX3CvY(MjhaqU2zm!q zz9wt3H3T5w9F4VY8E3CKS@iIbOBlJX5oGFe*o27jHXk6lQ z65m``NheF$d@mRjvS+vxy<1dm{6s)%E8M6c%!KKD1x3LJF9-F_C+sqpN~|HK48or4 zCAi@&HxfPSVAfzNnul>^AUq^Z!i@lNs{hNOJDR;;HELfWY(!?@==pP<6|r zm;_gO-ZHi@AJ2%oIgYKR>1$W)GLQTTgY?lV-x$To$2~VXr+4O71#LxP1961VayGt14V2Z6Gmmhx8Vf`@lcGDv+SQzd4c>r z?JfMFA>p!&Z+j<4yZgH0!CXG3n_Zno`=NT10F#+skBt}#g}@VT**cF6qmTpnIXJ$k zSpXazAoop-R|(5k?!=3&mV%pH+im}XMeD_$g@>77Q$*G(<<8;Vd7C9%A1i55qHO~IJ5Qizx3UcNjp%_~8pQ%~R`8LzcFSy1KZt9ZeElQP1 z4Ek$w?K?5g0{rboZhU;W2f>)83MtbiEpa@ltivbu_17W^ydg=gDNoGK$v1}g1)9`u zNP$aD0cDH!ACCvrSh~+3QOT%Vh{j{p$+w%k8Du|B7qd zo^t)b$6^8XgknC2N*sWdJAB2MO#|Tq4zg=Ekr%|$mAcm)Z^XD=vGO63v|0A;!hUl7 z>`L;d*5eyisHvoqx*sXM^htC>IdZr{ojmRxZuM-I!*yx-Bo2F5!&9`4pXfL}NmMs= za@3w-n!(VQRjXrn>(!A;DmoJT=z;2={oGC|5GU}2MnttygkV+n$-p3(JXJT_$g`pyo=ib#)PY$ki@S@!gv8)uhjxb}cHQ zh&Af4IeMSxuqP|!^fhTqBnTu z#fEFq&;yMDqj-lK^G{TRPRn`5(^+<4>tkthaQ`c2dOF)k-w`3XuL9ecK^?h27EYh* zL#s`+*Anzvy*}x@!rM+6k+4qBx^HpmF;U2ZjNMHJ#&l%K*U%Qs@ZpgVeW|RLe>AD3 zyv(~+Guq5090JQVpQa2rovh=Rr>t&m=;@*jGnI=m8oK%AZjvI1i91|RcnM}~pZ;EzY)i6o~J}cSU=A{t`zMc2OwlhAEW}J%~(zl>ri0mn*kr(Lx?>^I}2g>)N;9II5pPY$N zN+DkE;2$d*q z-@P&NYdE~!%9i8^EjuU2C$&E&2t3E4XfoWQjL5IcCx1xTNWZ$Ws{Q&VcYBbEg>1%I zsV@+~vF`cmgwD>BzFHp=Ii}1)E<751V)=Xxe+J#n`?Q=nRIok1ysc@~G9e6vFng4B zbsZetzt8d%(t`KRiZBx#4daQmin}u(KxgG?Zce)xS@Aonf*&S2#@^Ek3-uu1eWBkt>WW#ACH$Q3Ba`*x2ogPF^7P&d^{{lFZzk|&1r%gfqcst7~`5d&G zB{9{7We=Z;AAq_0ZfV!SVS`*4H*KQyS>Dv0!e_NN9KBrlfU=!aR7|wGC~9-lwF!DS zUTWf1l2$SiSI(xSDCAQ;yV4{?r!}asgx-Z~^Y$=Qzq_Jk+!H=7ON>v4Mg453bz!@Z z0VVbKA&V)%EI5<(1UA+17$e3kDd-MiOxHnP+Or{%V+#b{AaB8Y<@QS3^9#sQ zTZ20kNCKH1ej}lCS5pO`$q@dK`>Ic$oY3E>fmyahuoo%w$jVCF@>2Ah^YPcm!r#!s zg#k(J=ZkQMe99Y`bB3Y-`Q0rfOP7A=O{T&4YB0~zam}$uF_3qfY48Z()EyLD?t_0$OHu3OASt*QyHXTU@v$QfynS)?>mQ78EQ*+ zl@qGP`04;)9??oePuxiW2x`+BFTV$3T)u?@*B6qa`noed%C^x$8ODv7HgtX=3a$D| z(_bi4J5n!d-arGrqvd~gNUz8X=J#q1m3=?%Ey#eh#_3$|IXYvON=KY#cgV`0sMVW7 zm$1dP+p-2g-p?xLqXSd^vnbu-!@9fxyD z`r1||6EV?bffjejXGy(+(Tb0-;U^}G?ef)Mfumd&_&r;N$E0r>k(o{U9P69ZXToPG z#LmR2svW`hwVCNJ>r!fEb@ICiwB_~8GhL9n+01;Y3m?U~jBck6$$|2MhUINf?8orr zu&-~%(!hsU-eoJ5I}sOeLPRjyXnTb?ntWGxV&RvPw|`zvGiJXqszk_W)Hz-hj7?R- zuxaXES9C~WQv}S(6v(A3gJijL8R$Ea=@b7BNSH9&}Kq25sU@&jYx7(L6{feqaC62RyDcL0sVRx-duP*3_;K{1X;& zGgwEgm}I6+&LU5$TTkWG_G2b5SPg99PtyxmS?Vf#F-cxku?xBln_A*urvW`eoa+q_ z^0n#E(2j-S?;yLR@$NO=5hD;FPiYDN_pQh!cq_p7rvl7{+T3j~hn`(?IO8pUq9;bx zIA;z4Eas}x&x4kMBZB|uY=It-L&3(0c_)Vqe6>?3&H#7*?n}#DZrM=TX*YA^(0*R9 zC4A8A`L@r;8yRvi5OQ7fV>w7OE#dyJ#BBPbSZ_y(J|wx7GLS%e&-mx+$M8CIew-?G zK_L!aZ&;WUe58M9gXX?>J>1FA@?Si!DA}YgxS-ANq^N{>C*(4tW~l;!h?!&ZRe<3{ zWE_Bw-<#o#)i#-N3rF)`8JN7FU~V%iS80&1lQ>8P`1qYayxEI957&4DaZc9~{@Ij< zS#5`jU)JcBv+{G>j%mF}A8Y_$k=)~%TrVAjHOGM2FL;`GXiBS*IaqviL%v2D=aHZP zHGTYbCOcMCjk)hzvlE(+EqP0+nnnr-*sXAH%@s6P)0E@bxQM(u*+{VOG+>;bD=0cw zE?I(Zq5!k$s9nZ&49k(;dW&OZ>tG`n(qD&-%U_qI&C13{<$eB>M`|Cq@d8@gF26$P-_t$fTI&}p{jX!Dmr>>6Q1Ke=r$9}K>Mm~tH8s6S z@MzFTi%pAqd!?nrSQj8@P*Q|G^R=K}+4*4Dn5DJ~+g`ucWE`UOZSO^mDfPCdt;Agt zJUGL_gwj4Qj+M~N8Y>W8#&0Rh%xaI6*6R~diOi-R>3w47t8=0W^3pk z1T#)%uAaQqb%r;Q7$hwXksy$sQtqbzy}^I5>XwbtTGIffJ0#JDfgJPBR(*zLhsEog=D`t2IgEY1CC2y+6kY@QbF=c#t`8 zc=3bUZnjX*xl@={qeBP`S9}kHJS@Gfv{TeZHZ1umH<7Ic4)!dIDV-sEMlQYfrB7b1sfKHj7Qu3rCa$@RuwE_3{5>S+j^1IoiN%x?ke@ROPYkT zkuwJfvX5D)e>68zCb9MfI|}j>pGsfIY5FS8gZ!rWv5we3Tp*xYcd zp;Oqgl6^QTAo{O|{FlB=8V;?nyrnsPuxKbOmYW+cT&vKdCmrpo>h?CZ~ zYGYjuGXIEAcv*B@h-KxisZcosoX>}=bk#BI(X^i7Ut`iyf9HczRU@_t4?VQ&OW_gZ z^dr%IsNFo+2v8Q_zb{CqaVa>a3?zZ)7e7qVkRI~P3~tmPg{iAR0Cz2Kh_~%S@fg<8 zGbPystf9ECpLklt{#vby`30XExp0A?ZumK}m186F53NlQnnA8{MMK8ltb=aga(I(9 z40-3oc%{ZpFvRZ3M^3DmY1UU!CJTK3-jj`h$X_p*TC+Z+VnXH7@K*cRP?v{{^iVW`O7Ils^< zsSHN|6L@H--(B1HjFE6ioscn{vJ}dDTS@s-Fsbwp8nL?el;jI{N{R@%ek+NuZV@UR zo{O`ArfKaew32PX^kE?q<-&U0?9VJ-q=lfJvIV8LYV1eI^l4<~SE=4esTQ{5QxFVsc9G>Q$4LDE|vbnzkQ0dIs88A8i!wKg1F6!Bu$)4dy$kI$MuB`jZsL|J4u zpQnJa^|JR|W+5p<6Nh~r9NL$7Ld>el{+bT`oGhu!N*4#k5Lhvh{7-fB_JaYD(6V?H z@d9=27vs$MWcOFGS6S+hU7gZbVxb+x6%hiKwo$858=pvEq||$HPAN;9n_G`kUb?)P{$p5{@@A?os)^tG^hB3B209P@`?qjJm(ap?vSNBO@Z)z- zs_QvH_r3>**wQW+9xGt+Mf4_QZ>XjNxX$i(R$V#V&Z$!#)P2>2BYcSZo04V$TN7VfCBrtGrL?!wjH_=oRQ?j{2xsX!G;Jj8S=eq2 z?Q1^`;tv3FYgHAv{!B%<0StjI201j~a`;od3D^T1WWAHJ#jLyrx&yPOsRTK-+R|&_ zQ8x?wvaD!8G@btT^W}+9wBgaS*S-`u-}*#}tjecqt6zmiSYIkwuC-J}Ef{3`9_ODL zxFXaJKc7EZMG8tpbX9^l)L-fBeE1TV1U-w6&;ppun^R-Fk$w*a672bcG{D{cL|~M& z=$g!Kr$pYAUS(B@hAI7*MU$zW;uVlI-$O)9fq)HC3TJrM6+xmrRbYLUc-{1+|W${YJO1 z_=v&3{XEns3rBZ}EA%~Yidsbds@9MFcg03|3Pk)DJ_+g6*A^au!Tz(@v5XoO;D-KZvLs~BWZ!jNLqE!*WFhJ_%$oq^B_QY2pMP6} z$reA9wtq^XE={#K2Qe1no}jf0L1Xh5#4tTbumn07L*Zf{p>A99H`mVN&`90Y3G=5j z*;A9g*$s;Q9yV7$n%;rloq~8h$DUy;rI`vou?Zb>JJJq)3zjGvPR;!1sgbMlKY|*T zOQIsnS5m};1?&7y=3n}5+XOaX+PJNn!)0F6b|z^X!FYe>zG(Nn-l) zI3>H&kxX8ETuN7(RR7np$4fFt4TX%PUV<+4fV%xg{2qNTs33CW*7u&k9!PC zH3qrRXpP%wrvoO)MKYo+uc<-v9C$ zEoZPq>JW#V56-P}CJ(P$hQA$IA=3Yw{}|rw{hF^Vp>oPBYRFh$l|$^`F%YlUfct6VA#l%1)1XM)Y&+eWMzRlo zH=hUa0P;*&N5$1%EiHf~z-lgi=Z4rBbx-{N6YO4)v%jT*8Mq|ln5!+AkIg(fBHWD9 zhYt_8w^|t{qQJ7R@~t9;fCP_*H?Pp7qwDWTJ~Tg5WO9gCpgh<`*=7VQB)-c=2kw^%Uxk!S*LMH&;2y} zukiHxuW2doNioydr)|pIvrLr=dHHu3{0qxg$(}@Lt3@u!|FJ$~Xu@CbK}%xF(X$5} z?P$6CBBTH>BAVi0(DS1g)6vazHI;y;jQUDhJi%6tuQZU)fsYxT8AU>8zER@Hv`7pJ zRA?1*O*wo8dy+xd?4C7 z$<-jysX&r*1CdOpG}cn?He6EaB4eHlZ$Y0ilRS;=1-eA2LDtum84EC$^ZbU8g7GI| z&3ZY}lVKUPBfh6oxx3^92o6k<4MV$qksHgnxd&4jzIx%@7|mRD0@=A%tA#u)`2MpKr77{o$$ zJEc&qzxi9)Wuhw{jd49Hn8Px=-Jt5j^DJBvg$A%(s2IZ!ule}6Tx--)70$ggQw^be z{m-1d>h-6MdTP6d*6?KeED=`qNvac-g>i?@T7vaMx8MYH9#ca8;QH7#^&DRd|d2hH2BE6h6b3p)1&p1lnQ|GV3z6Onuuns z3QK|w^_)&dR=Gxt^O0jzY6Bsbvs~JOJ`xXTUq>+8`?*sD``GD2`FF2aGyqyqp zTS{aRqz^m?6h-({z>`*QgAmG2kun5crYt!le)~M@XhYFqG*u+QfQEQso%E5Z!_#b! zL6&OxA*O2>VB-4<<}~~wHeV%v*d%68U#!24Q{;`Ro=SNaxcjm)rMj;P>8}#B1bBlX zV^#=u(H^RNR*f0z9v4&kH9?Cm^^QCru03%)iWpl+&n2@a#gJE8r3qv`;n(&J52%JY zkM&maeO{>5^u9|2AGG_!cl7dSbXKyArJp*0+z@}}qIy!li$}r+70VTb5+Vh2?(J~F z*ZufTuvis6op`ro#Rpq?-9X=Q_t)CBU%2V)cT+nge^mYli%=Q=yxHQ~WKMq*6UmH? zj(F#Av&iS#7`o(*UBfcXE|0KoJmaQpHxym`AHiqq8Q%z`oC@Uck8d+y|NL0)@3DDW zYv9c|R1o$?wlS#)&}O$>OZAD$D3}W&tAr3OOwH9kD!82g-B9uqjUhGCy3>H(A-${) zdQ~mIHQkD~YQP!I@vV|E%q}y|Uf9PBaU=Z$1T*gI5#Ro?F)30oq$RD95-ED9NSS(Z z`=(JS^089;n@?!+JBquSDLK_YSLfPUE@H!hE)-%n4VBDbj&=Z6QFWocrYd@mf{}yo zEx;a8g_aO7?;w(G{;@@eR%=Sqir6v6KTqSOK)b{z><1;ZG073hXKf|~7 z4U6T*c0{F@3mloD*{UI;JxEq@D=yzWJ~8k2;{*AfApcxUYKkDkTt`K&K+5|EvI(lj z>d&3HGa9S#{3p?I9p>j`6bh}i))-V;!+$ExSr22hMM(c>?`>4T*TgpCu6XkPF!`rw zRsVL)+gXb%rW_M8&3Az7Ie8QXh-INVSsQi(j$O_H zWm~JH;Bw#6qGo$WkyQ*H_8bQH?LV6Q&-CAD+`4EW!a<3P^WJ`iQ)SK&${*FCC*{@zM@T{)nvPNj^)atEAbb(&!3mw zXaH}><+bGQ%kE8;f88|5;A51cT2AM$Dy7##N#5}mdsyN{Dp>$JQb{ks(RbHry^>Y# z-%65UBWt7l!Cgtx(p6F|b&W8Kg82%E2NaQQ$8)~9T}O+YqZh^MHfZftqjY`jOa69( zEkfk?N=}2lJl%0_$86=gg1d zVQF5U3cBa;3Jp`8he9R%TNw*qSzgdBx4f9Vd;OAgw@&S~tkKp085x=QD;9M7uDwIM6wvF0q{&1r|?(lB>{0$6k{aaRPN&A{N@S zD2U@GdSyxIP{#C}Iy?%5x+>3_W|i_OpvbW@>_+X~l5pCS+q!Y^e(i9& zM+KaUq|cuE7M{m{&D+!NyE{|&tQJA-Ssa13QcLX)=)Pp%E9cnCDErGeBSwQKES1FK zJzk;e=dA{I7dr?vWr+M9=$dR{0IrXb4V8bFQ728%R3N`kW$~?Pb&{hc8DyQv^(C}R za;coR{sQbmAzs97)BC=`pcrHz*Q)eo%&MZNkWI9Y5x2 z^&IQRFfq+DW(+PxJl)U=eg1I}k^I^Qf+#K;u}_`5u0DT~$o1>H-H+E{xt%61%C_JN zkJX82v3l|m|CtgGER2XjiOW1BFjm;sWeBM;p%FsLekU_qgG>bC8@!!ok{D(}e0fYs! z@4pwWFvOw|fLX}wQiAE=mbkf}w0t;ginKhTq>uNztJ%f;%1#C5H2EI2$%=g@X5~`erI-g@!~o~8MUZdi^zVuB zi*K)lT*o}JGHDJUz{@e9UGn^4?yw~#+6eP95^PQsK*Y+c| z6dU*V(m&O0v#Jp+;(gyxD1vYIOnqf%);``SCm>nds!f|r*a{VxP3(cyX8gI*Z$p2? zJEoHU0i){@w`ZLL<{xhpU1lBL5!<^}mDwsRD>EqO7{J0Hk7ts$EprB^0Ou&ES#&Y3 zvFl*AT-QZ!zr+hX7mrkfSy(k?00<0JA**_414iBKZPcbwJlXaSy5yYak7UgvWREx? zkDG3$bIzee!z~;K?S2vapkGhRUg`UV4Ws(ts`LYzt(+2;U}}oVIz7LjaX#;KL{PDV zIae_#QcQdUQyVPc{^@DF5f37%jG8*QhO%iSMtbOyso2ZenNZCFL_^RY$ojc={f*9S z>9>wA7O4|cpSm3e!YKFS$X$Xly>hyyhb^|@0II<@?yq>H2$Fv}2Ze9~pvOlC|rxuXf>d8#01uM%-(oveu{lGL2Td6*( zXaa|`e}oc;uhPE9RTWFs+%6h4H(`3(PQ@}Wz;g2zcJA8Cyr)RWW3G4aXFd;Hzo7hf zX2bY!HNSFh=Yv~YDATty9o#Xo7vLXw-0ksA{CbJ&gncd6U117zG*cZJX^ag%d`+M0`^e+vD{r9cu zlysV^09H2V{1W}khAE!ck4BrOT@X4c@v~9iP-;dQj77^`9ZW&WvbN7h16(6AlX}PA z+4iBFqVQ>C`4Llzqdm!zH8f(0B#?QNGEVkKpiL!tbC4J?;m`-v#LeL5SZwEif!|$^ z9~r+)uhFxNR6o9HL|PYybs?VtcnVOb zE3Njll#Kq(Fz#Ipb;wLsc?J z3OY;l<=BeXm@zfIOK!m%9Zf*u_Qk6Ja@4p;Iq}LE!?(XHxmn%K>&em$lZ zhpVIEL8dal@z_SK{#1}F2|xKF6ZJ_ZS4Z z^Yv*x>xqF{M;d897}ha-qfcu!(jv{KK3!XpF1?4(8Ab;oF?)ttwjJ67_)j|6mc;Vz(~Na8iok1dF>X*!$!8lx6pzBjqw=^DOdb<;taT|+RBiKY~$M~ z_tMxHv3%znn^(#2z82MeCFyT$)ntzqriWJ0^b`B|jvtsjUk$mAUptg>Y%2Bs8_xuW zYm0=PPEkUuRyz~(8C$-`-SDo*(HOAHQs2(*f>c(4>T3iFYi5pUO9Fe%g|g7HVB<0b zKJ=3(n|sS{8ut)nJ)dBN5BjKQxg3}&O!D`NM_dl$%g{>< zZ+$$lxovS>^8ApGjmP~@z5XHL)O`D~$`9Q%jl=6|S9v(g2QFl*+;d)ay&o^@e8?6O zB-QdT;hrN!@xzDWaQAa3J_oMrQ9@l0240PI6jq{*!IwUx+a{P`QPp#C9|k({O%TSY z)iS})N5dc~<6j)>_q!g=1y<$z9gl?UwyMNHfx!x`I6kM}R=Qt(89NAyXx2U{v5v%KAV>5WkP?OlOrir{N8HP~PkAbcS;`>TtL&m@#$WAxkI z;N1KwurUz`21XN-HD@q!m)&;$S4ZVytgNK3>8~SrDA-aGCezUgb;NTVW77zBV z%s0C8*Xh#yA-qZZMPc+C6^5}b?i);=gXrul$EVaIwDJ_=inpvgN^v|&uy@`t19r`} znKt1=y){QIoH}v*vo0rmOIJRoMo^+cuKuVSGl*wiBGAfvk3tsHf?fS)>(^)2cX;6VTokM$!QzR{rxXobO=B&5h6Ir$O>22-c958otY~hwx@AnTuWDaANRaj;2w(V*f z!~qpa`|q+#F1YT2F!i*~w5kA-Uz;ma76M?#B z#CP;+(pQ#1zbCUj;_b9ql#G@(qx}&4w^DM#E(0W?rvqwmKk6 ziUv$W6*?orO!WHGR*FBcIf*}_Mt1?2xUS{eZX_o%(wFmJ>iNPCxImxHbxeciO%rz?D!b5t$9~};v)`TIXv?#!X#s9p5b$r|rK=5nW z*ouGWSdz4D6cyuhx+(yQaFC_;RU7j7P@P(cp{f2)46_me-#)Z(aHA#geZRk5_JO_?1?X1+aqZz_Qv5!#SMZQV1-$_whLA3y$SPp2}IkKE%?ey(>;cLa~FUtz;3hvsY+SYeK|^>CKS(R<&Fk@^F5XA$H*A3<&-$&bx1yDIkfrCz3v3i}l@+3NYqP0?hV zaFS4|`pk+>!G+Usps*!dB?1wKNSojzqBykj%Kyx}1zsWKBUXr!jOK}Jqg%4^9}u;g z;Z8^!dvK#Y0WDChGm-irh?7ZQeAo}3&#>O%wFnswuO0hjV2n^pTptAA3C36x_>rsH zQh)U%0g2mRlk=1|%>dhfAcaP8tzW#4bBcYwF@V`&N}Nf)`|8hK9asZjjO4~<-3+|% zsef9d$->KINV}mJ2YR?Yffg(pVtKYk+ZRxiy4L%0l&c4EwDc3Z@(Ilmo#8e&o(gGp zKF3h{M)V`!1|+EJnhao%-g_JIIBfo*qV$JEx`e!zasNZ5TZx2V9ofSHc}A^DZX zJk|U4r}txc9x{hM&kCH=Zu47|BjlD0*MQR$V}z_Yq+>h{9}GG=so?Gu8u za8Ya5)&2~@LLADQb7?y4AEOBr?%>HVRP=+|viVwMB42nD|5dd;UPLjQr$N=KMJzYB z!}u$KxKq^C)Rm&B{(U0kthH3a;T4eS_YXS4M`km0bw)! zM2H8EKKprmW^~Bjp>F`}c53j6R`{pRvedC@Z)gqkV%?hz^4N!9M(xy|HiBRLGXO}z zjJD<xcFa9s#FOZdVpHZZOU_8Cv9Nvhz95u97dJYw)2VPpaj|4`;a* z*Cm7x#kd)y#0-p5gw&a@MFRz;W?w_em!`OVaL6@?#-g7|LZNWgwx2)~$APq`|e8JJ0VP+Uy{()THI77?lcGR_EzPtJx#)jkYG!_F& z%{_D4uswPs{^h1mkIh_3kcxGJUrWen9yqPGim55e)W32Lu0BO4#cx8_%z~RGo7`t& z)p7PC;wUWpdsY}owhc&f`Ovbv!Q2DO&cC*;b9|#`Rh6y!Qu}*(X8Tz=5BE9F{%EU` zRwBlqI{vV-+%%3FO6Czyt|WN)5_$x|8#hO#^xsofeLu{t@yr~+rAKSAx0wzB31@d~ zUa|=HyJU~mohN;t7lD;Y(THYF;%hea#-BU~^_<^Lh7!W4p23yO4<@VrnjYC<$L3t! zoF@p4-(C4B*eSl~X^_zKk*N9j@q_mkCe*VkWbNHLbGaF1s?M_`M`dl9=!j=zj$Cic=72*(`Lwwel>e?U9Yv$L)ThY|(n1 z`Y^%^0@|L^aM*q@SpXkj`(&M!#c^0XhudSM82^E33QeJ2)|`2m_BITqvTL~X)P zv9hW!CO-RFKcl~Sc}n0;Jpj6Q^kRsSewFy|f?ML9;*Q0@j1HIkDnh^!CSxCgf73eH z)L%9ld0!{D%b%$e>pA){1r@~bwAJ3p{Mq}X+8d{wH9;H>PYv*J1fQM%j4vPS$k>{A ze~Y)Gwnu=OsQ*Od(5COolV8>&lpF}OQMhPm7lCuS#z%h_`H4!mYL6y~CiMpPpZl8j zp~rq9_mH)tFSUl1W5*YoY%Z?8$B6n$=eNbfTy39k?lbFf_E^qLpIRg3FCev$Sp=O- zgr@&Oj`0JUw`sA#BzP8m1$Jt}?%FuI!iXt~RD*Evb)6k@cts+W?z;gWkoi845tDc~ zA`-?ixM%n&W+}OAw)s63@7`OjDYjBsTOI5iWcqUs*`oBJQtjLvONd9ADKYYY1QVbB z)ig9HSidlYCU2`3LI5Lw*`_|Go;^AvoRbm^al$g#Y(~=HNhvmqFaFh9CXDnduH%iz zV9%-NhgmGRw_W#dA!ngXlk52gD^A2jhX1M`#5LdbI;Jm5j^!IK>r)LEUO|n%d}el} zOe^?iG?d=%FI5M-FBkr*@=0WM>222^k+AehNsS3FKBW8%!>^z$K=S)Vq}TIZNMeVC zpe@*$E&6EF4Z!h!Qj&xss``f8)o-7#}|&RO)C8w8l-Sh2)aJH_ml%a zvR>vKX8OrQ9c&bTT_ElA20lmsW{a_O?nv9PrcWKEhreAPPLh30Hl!sOcG+G1F@G!= z_kV4@WmH>H*RCC;1SrL6p}3bI#Yu2Vkx<;Nl;RG-r4%a;fdq#TiUfz^T7eb_PK&z~ zcP~ZSetFJ$pZEOvGBUF7v9fov*7~usSLU4eRezKAd!n{xdVZOtq`kSPE45yOA?ra( zHhD}%UZptRdTkPS+0?BB*D6P1!)pp;OJcrli~ z5Tm9%B06FEFo0@=JIRDf4TY8QnqzYGpkTPH?hf!8+KiVhWLovZXcWK8-JvUF=r(h4 z1!wXR2b$8%$TG3~#!NT4{sA${gmK&WZ_)rqwnHmGM^HB1z zY56=vHuOnNTv~G`E@=8tdTGxrmwrJ8YKvApG!wn|;6O{REQ@!G?Lw}Sf#?@$@U02$ z2D<+Ow~<&%>obY&GYm0`Gv>{XVx$bdx4KpNY&dok#}sdKVg;!lTk0_g6{9S)d;bBr zpW&ZsNJdhC2QF}4tQ;UsVZ%rQXPHqL=r>P^_9pQc;!C3IA&MHxxSihcjs1K5*%J5t6>|}A~`eiTK`fMcaoqAdXs_;b7-c5$LeTi9<-D zO@^!wK-!u1*@$)bYH3Gw$hf;F`;(!A2FoMe1oe^fL zg1Mtmr--D~axy@F|BbFB{e-9BWm%A*fF?)i2Gb!HT&|nF0@*c}lOr>(8usl!rG@}5 zz@^`0<9Z&B?q&YG0E-}l;mu}WC5ihL%=Mi$PVH5s7`4dJt4ClqqX2&&oFaoU#Zs4$49)7dVm+LoAHWVxn_IHM<EGuK^vBVz?nR5*y8A7_)B^s7d#F(TreXqwsoVppqWVpT9R8&1IyOCnW1 zWvVJecW-!~cTnRr!6|Q>$Z!#84?Z?-rcbA|X%iKars|j57mOcy(cuqzi0pXUw;~J@ zrf@+_p3L4~ z3;V;jmK$V-7DJ^X*tgF6xAo}D=lkw2jBjoHGJcvU{jfZF+g7n@A@!OI7M&DzTes1G z3eGKJLd>Mp@IP7K?ylN#m~Is)%3k2-Q-%Y;HQ5p`Rc}TaAI^#Uha@>S@!w&23w~}- zxBr?|BZG3*g48`&1fVnx9Tyz6l3K3{QN_HEY~7!(!@ZHm(UYhc=JWAp!EL0m(Yqkb zC@tFn&K)bv<4@(x!OTPd25tGxF0IFir`SIXH$ zJcND1%g$<0OSR3AYxk0-`ynUnP9d3rjakJJ$3_lB+pmT*GJX1eMf6o6|OLw1D z!-!daj9k}zc~b14`1Y#4R^3&%GIG?U)pF7tT|+aw_HuwLjQB$KvaozeUmx`{PmYH% z+iG6i*!r1}TrfqjT~=MsKY*AR(|PXdBMUfBt00f<**6*6Bb0AnP?hJ;`~C!e!`bxK z`2GsXLeDQI-3MIl{E#o_hfT*mMUh!s8+kVGo))UFi2%GMt?@%$GqhY7*!9OaCBIuZ zF~f{3Ud4#@P^XP?$0%sH@VUKP2x%3#nT zVa4d?8FjYVl-C+2Mc|5WCzlRgNxn*ckr<7!Xq#q>PJA8TC2Pd+bV`Sb>}FcGwKGen z{gd;1IGB`(0u+_mPtP#0gG=}Fp*|YvJCi;j#MNw(miWDRza(XM;Oo7o9)%{s{p2jV zWC`-jsvGq~IC&cK^rL-R80h~20#RYfIuGlxn(YlQ7_}y(!TD!)itTGUZl?v9=T&A- ziH4r-!4{o~G0VsU+ZkY?oU`M{wp8A16Oyx}+fe@8++Tj)ge5*d0?R*6r$!FzlxjP7 z{D}m+@;BDDbeO$H8+S%hQ3FAyL}585q%vrq3nCo5+}Yxx!1E++C|2_iKPe%w?v7u} zU1I^tZ|lM?p1yJUdVuzjYHN*4q}q7LEDN54^PZe}sSxY?Qv2^7KVu@N>x1e3c{BI> z8J3a6qkvH$WcScgtDOJ_L`*0Y&>vfLyo&RC@#Hc1X)P6t2$jA!MkbPip7ygG-VnlS zyHt5qhiq~Ao5vd{Y+Ll$w58J1k|u-A_C2oz8JgjwFJlc6R%QMIM(v_S(+}5-27q;; z1jl&j{Qa?Gzn9NWu3JZ*X78s6qu(dl%4f@gLPBzC#UD->J=EJKlG(%#7RE7$zD)TX ze5#_sRNt8y@q%vTX*5w|rPJroPUl>Zc{gpfndZS52sXpJxf2`~TpUKXduFOc^E*K6 zyvXLwBw1&lw3O_$z;FsKAK_kpPOB|JZD3_XCAcR%9C#0B0K`>XSG%#0rSF>QBC(6tVq5(sM(uw}Zuj&*T63!2Nwzwd|!^s3}Ke4JU#)T2+L zi5_G8B;Quu^Q5=WyX3NhS0KtIN4U#x_qP#$bS49_hfevShWD9xu@2_yet{q{NgDdn z(w<)UuUVPcBW7~wey(KNcNYF!?W3KegoZ{+DFyRP@u$4HB9jxw)G$QU?Bk608CLpzDAoZE4I6letxUiX~7*tPv5KPK|EL#acsPboXV+aJt@-6PJGBP z|1nd-I3$zGmSI`S+P}(TgGzpbFr&}Z3zU2iK?^!L4F7$jpV#C;TO4Fom}coPXZq)O z?Tz(qN^ml7j^r3q_3+zYY8sVFn~a=a%o~uP51Euy`^)Xu3yzK)8vVH@*=tFt7HyKz zd(XeH>sNhT7a;yw9WS`7-%zOki1lfWs2PX8F;D+aU=`A0aq#KEZ1qGZpl$yB$vsf2 z|B)g|*9iEK%aJw$D$8_g=IY}vSm;eat9Q(HNwBMPtG`$dcewxfgqV&@Pc~K9S+d;i zkoS`z+#YVZDtw`!v5?;@H2iI@Lh`0)zW>yUqEYNn7C*3bU`ykm+dF6!#GkA@YzLAQ zmb)i*cuddFz$wcTJPA>A#d$)Hg}9ic|2<*46faWSMc-4kTWZGH5_iqMPC7TW+-=Ft zR2y!;Difl_{Sy@TIe42Z*bq^{wwAIEjgA)*(k#{Q5`o<9$@pGB^0j*iq!=&Y;%Wy( z+XO;>R*uldBkAkz&)o4X9d&cNa@>BDJS)g<J$LUDZ@oA$#I; zWBg87jeRAmDJ)sveJ38KH?4wyw9#@v>64&?)+YyA1_#u{`_7s^GA8J_O{jJ!CfECG zdAG8zT*gIJL)1i%=unC3e)YDgor~aR(oWclgv-Ao14(H3&>Du$Ug@}6u`9A7QapBig{`g1-*uX$feh5R|J<%1_wX4 z$r=yS3^DPaqr89;82j=bi@~f7&ImU8yAfa2B>Q4Vv7P~|9}tM(GW*Bk111mt2)(9+ zMS`@13rTqw`VGszK=v3{)YL~gCW~5k$=cxFg3Z5lMqUk(9RVOXpVqtvR^G0kzil=6 zF`5(ggqOEmf-3nDXv5AAKlLEx9=$I;!DX#IzgR^t)JdC|OipRvqUG_Y4M}}-HQ!yb zf>69JS?lc+uD3kxh3sQiu!J8CIkp)u3(Zi%Y!KcHLWkz$7cNPl@hxLV*JA!ZS!1mM zW=ygwnJ)|D4RGO%?+NuEcDs+CIwHDX%SIY;(#ya_u(Dfe(2kJ)$7^e`+RZvk)o_$- zy8s?g##@@|&!Qt&?vGRGCnDvCX?|?kOm&ECT!kp7he%o{B z2Y;fBcuY43l8Zx)9GafV3nM7S!>*aN>dNX8LB27OMmtiy*Y{R~T$FpeFK?EcOLLqp zY4%7rRE(WGAvCPkM6~7}%|Z4J4u~2%Gba;oFdB4K8L{C=%IYlZ4YNE8-tm8yKQ$K|q87m!S}Z^! zW69*l8m-1us04=GjN9zZNnJ;z-)>>Flo+D4@R4$mzrI`@JLHE>wFwQ9yR$goVA>PF z?sJTlnwMmx4$gS7s!zV@v9CmR>gVskw^Nf=vpt`g(E;A?-0+k`kF&!xwl0!Ci25_s zZW|`)tU=v-HZ3*s(xnJ-Rh=1reUHj~gBtTI%}~#s9~xP!E$Rqp2i7EmeoB}k)j4yN z7_;cd>J>D{cjw6(zhu_;cf$#MSqnVwIqd{%r@tGheASEpp0LoZ{w5493|d7=I7kRe zxMm(->^shX$8x>klQAJo+HQ6j5b$Tra6IbsX9I-JArL;LbP2Pf+)e+l)nxz? zM#a1E%j&j7B6?|ubXN2EFw#0Ue+utlNWO5-yy9)TB-em z-ToVRT^pO%}`r23J50;;%+aKjgBl=(L>q! zm0NMy%yBnjC&u4Ju9ZB|UYlVX_t10^QRjj()mw=yp5|6-8^F@G05J0`#Bs7z=xNtC z@{9t((s9ZDn&0E7$M*WUPIe)4N(5=V3Sit~>IqkeBS2)PN5vT;Y+!Z_(AFtjx;fNcId)XjFY=+Vub zO%L?;E5sT$;yWsgbl(}3_NijvX4Z=mP$4os3pO<4MgP7i>wnST9X}$qNeY`xSPMZ{ z`%kL(ZTE#e4#Cfc0GTVr2hS%`PB6CZ4Y1$3%+Rb5vIrD;XvNy19nMFI%T8!H7Of)7 zb8yJC70DIfdIamq6}z7GuwfCbdHt_1Ps)wA=TVNG=b(&!Fy{t^W#SUPZK}Hcd|EVamT8F*xH#Jsc^1Cr0 zp}O4E(R>`oml*D?W}ce7N5SQT(7xi$944sPASig|Y?}So!#{0bOVf9hc;p50{n0lv zCVVHw3vrW8HiDfnjI7X{^reJG-|9#t_Gp83=kYw@(zMOn>p!r-CgZyY`oPreZ>}9p=QEK#lcfTCD%bj^@8vkaBu-APrlJ$u_ zepBt--`|mWKg0?q4ApKZo;r*aHEq)ESNyX|%37`v!T?OzzK?+S z_*ZbGqD1a0oG$FOrA*WUU=`Jfh3fOX+tm{KNa6X})gy!UI5u>sYf0`IR2CA*Q5TPX zGUf0>HOPM>sc~~u3?2>}39<};S4*D3B1NWKE|P7I1`x$L)_@rDIzG3kHlL(RmS!Pj zFpvG)mqQ4r@ugjF%Lme%zo>GkMHRO%kN3?)XZvgN>x<~Pl~FYCFUi68vU*4KmpA^j zfR85to*87GDP5~?jRN#f6=M80M+-}?#Tqs|30YLth9O%W>-R4q-1=kg6ntm1^!g z4YetPCG;0k!6Tl|l%BW+CCN4=co`)GcOD&|tg7weY;Iz1mGlnvpOFC_xmUH_teU(J z%+d%+mL3qy5{s-G5L-IE4g7Fi@e@ zzYSR5H~HJ`R!#;#nqyd01fG?g)fDsE!Pc2$boORC@dX*!EZzE$P&zpr35Av?gJUSn$+)A>sMp+R7P;nX4B^q9V2i~e3`1YU$}YN%>3 zOAs#Z-eQq+##8(27M>xo{|`_n=r!`WP0`w~q4_0tdDF%mzl6fMcmRpv3X zXq8}{$8@KR$OOt7)M~nI7LUq3Fo~D?EN!gsF2mU(l9)VC!sst7lHeo&u{_}$XE#Xo z(Wv#$SQHNIE)UsrLg(HmtgI$W7zVoitRC^Y6411c4Ds8ld{c?V$ZGU^mFADaJRC2-Mx^LC6j&KBfSg)ARGL;JWu=`^c&?D2$&-VL7!C7 z#q0y6R|SWzm^YF{@@x(OzZ>12vZBLgd2IvSX2nlx5%;SelsbP6Mm-fcJ%#DE7_XO#rL!kBoCBP+>$P;Vtr z)hz+y$;*2^^>Jf^*tA|JHRjysdaYuiE7`V04eVbdYfDmL1^ebAvLqx90=0`iW9td? z>6tf7mp^YLp)f-7yrML6A`SFv$kfAIQ93V@`JgeF#!3I)0<*?xzeGL+DQWK(Ng+YU zJ>C1GEEIwx7zPNC#*J<9HBeCl;Pj3)`XQ0e_!#g}c1aDZZ`!(v8oduZDw^AB{Ex69 zG`)&;T-)f+O}j?Qlp>SsKu8I~pSgIv(LJ}MgFNWXaQ*FUuc}Xic1gs(ju8U{yp18l z*u{j)X{&%D)d?=Eocg=NlYF;jb5Y$?hUrfj)}3T?{Xh44V49p_z|8e$Oe`p)I9uD! zNQ&Sbb~HYNg%g`?0A2Bed3SlQq&6_PW_Mg`zYuHu5qV`a9GkGLuaypsM6W$~h zxZ1pnj?k@~WrDrfs_XXcy6k<$3*&Uc<+?K(At*G-r!?|HsP`}(V%c_=>ouCukzP9A znGA$DM1%n>kOA=?L=?e%vBRsLCLT?@NOgsL^=+HezTn#lMRHYQmfwX9rtf91N*%6f zh8bgsVEa1CjAV!0v9uRaOw3L8s?UhVlvUo%?}*Ob)vPl~id|2qEKon`5-NQ%a zw_Nb~_b~KSI%d69NZSbhouU@_dpZWyXPV0H&=+W>zFl@%m6Tpmn`95v7VOPkIZ2vR zUlDI$BOrXr8#QxxYYdDN_ZzR}a56(Pm_*JlQZVdZ{sVw(i&pf+D2WBe&LX;oLL4zB z)9xi->YbL>lB)Ps&6Q>ff#(uOHu0mZR0iLYsLyn;lk_-*!p)l-DUxl7i3a>>K-#b<2Ms{Mx6 z;8}9zP&7GcU zn-urnz#HT78sGe&!-JZSiJ`xZmQZ(bI$^&$e@N-9B{InsHEpzhU#odUKgwV8o$YBR zDKR0AVsuvfOlppm*(I=+JK{?9D0T`;R|7(o57tQW1jlri4hz=Ek0x@42Y~9vz=xI( z_QX|+5gKiB#B3=T-^{F5XZr`epN36T41*FZ1lxYi3u8aH^n96o@66STg4iN&>(o7c zW=`ZY8lAq9TKI~-Sv69oo|WCo;qI}mz;CU&Q?RcvFMRM6^_!tZ=4&cZ02yp@GC+ac zFRW2wGc{q43W?t`)5ZH+r&i9DVGy?Csf|NaZ*z5~+|G@dWL~^ud~{xZiJ=JfV%Q>yU z(`wXa=xE$Tqy^3M8vf9b$0Pco~co(>CwNn2N zKx3+BSGNwAneNMxHNN8KN?O2MQ{TU_{=@&oFmtQfsh8jMGWmW_$JBC`+}GK`X(fEg z0W(g6Nu+7&+pDvhc0U;kDiv3Oy7>W7u$VHQk^d_l;Z+gBjU?aW5ih;P*;md#4W-lV z0Lj#!+56?1j~c z9ce?(hwzZz#L~t78EG>(cncAq=w(aag{AM`2|l%yuc94!k{QS%Y5ho`Z4~$_c=_~U zGt7Ja&(pEkkdEq9P?Mu9S;XLt?MlM8EHme#GxH_<%*9b6%fGy>bv1ktZy}p&_oo3i zG5xcwS!8N&`*LoZv9ed|7#;CJ%Ag?L-))t1#&1n7Yb=ELl8s3>5Qqt)0=AR^Jf)?T zgiMk9M3!%sOD0UEi;EB{)sa{BwluZiLxX3XaB16592-eAzYTJb!p}C(+P0@LT=_S2 zd{XblV%XJ3b$DfS_3+>8?`gjClH)6XDLg3c1;#k%)GdT_wp~_sv~;F9Hq3_2eW&K~ zE`#7lx00NDbxnG5!2tmRVk^@n)?X#A)d~HWcbDW+bCFA_xE(gB{Hq!<7@Lq6Xl2gw ziL)FSa9K{K2Ah{Q_D*UQ5=}HF{%!UCCnmltgB*7!ms_jE#KdIiR%`m^R&m1t?kaM& zxKnM@(nfA)A74L-ruc1`<^+2rBc!`QUiSMFfA+0mVY&yn4>T!tfS)?jMuT<@oGG2c z&}0UhS6Y5Y_|9q(NOz9<7nI{kv9TE&^`ix2RVjyqLH+EZlW3~$P4lWlur^ZcF#XQaqol{zjE@V&3b zk(r}*5a!$pLw*${zGMbXeZq`WK7ZXxhDylZJ6NkzWLA;6HPW>6a6=OTSUj{e z9qx`;C0&XAe_LwJC7;!`|`dA6(r?VuQME`x&_K4%MEuhi;b^^`ADU z%6JzG05=rA<~W%%`rvL-vm-_o9{+ejzoJGkk}`@QVB=-7b3FYAATaW@$%RtkQ-Ij0 z)ce$#N2Rw=Y32!nE(Jd7>NV5~+}RuJ^uQb43GJUDfd@vCDz{&U&OwM7-ZJw7#i?om z*B(oZ@U}7K840qiM$GIa$61kG*W$+~hmmp=5N7E=pg+YDPsO6< zKDWprKE7HF6=*P#4@AkJAy8z1ik2nsUx|oiOl+9W!(Afk~YI_r7*9yiz_WJJ6 z(SoDDvLwUHz<1|HywGowtLiLKv?1!h+CbXBw(3`2y-`1<+Xw%h3{>`s)5#j~p3k3} zx=WNe>}eG9`K&6S!*Yp?NPP2+FzIK@@tOg~IV~VnSmA{Fo=YyuDwF%~9;~xHTbC@D zCBx~O>hOG2^dn5O<6SYwErHeyCrJPk+xk$lx7cF2_&-2QK|jr}294WAV7H;sp4;~qTRMfvyD0gsLdIul zt>BFW6aFsS5mj%Ws7Yh3e37`_4CVkf02;Py^z}>({y-)O5Xnb%-KR=X^E}sWny*A7 z87@QGNx1|kQm518;|exf@Vi!&b9G{xvWjlAHL(^Bl)at$q{}z1EAPeH`u%576e*x| z?_k_anbsC;qf_=DD=vSoVhzpJ&J5FH77?1E&1fJDAbD_atj1;cg^#C~6>DQtJP)n9 z6uwfQ((Vi{b=VGvOIxhAkrZ0+uN6ZE<0X8L{3&DMT3*Y3op=YYR(`(z<@(|SWUon% z&&gwM|7v>Tqv#6M$&mR6`#l0F!b;y=)cSPOtKOR=s&5|LVnrebvf)Pv3T_?9?J#y` z`Qx?cOOKD^0U{8t^8%~p3ho=r7xb-AsrqihOGp>?i$?a>yiffVkK?Nzo3xAtd+@@Y zS)RabWdgJoLq)+1(j>&GQj5j{Ew>VJy4h+bJQpmZWTKNSqqh=`vxotbG zAimZ@ynCqdAn~q}w5V~6GcEJnfSfZub7y#eA?Ev>q}pH<`p>SFaca^!z$VuW7O_%( zQ7WC`MY=v+^lP@0=aOgO8`XE5sUlLoDS})&k^-ikc%Mx`3_f}3X3nKWr9vOTW*g4e zN#k9Ka!i1hMJEcUyv8Liy)Q?kZX>mWgALr>;`Kr@X^&pE6T*do=AWpeTkf+B;AmSa z21#!3lI-vX#vrA9*6J%sf169}2kpVW}n9V5m5^&3tAV=#(l|i5^Tld$mLFVj-?_t*abN_=ierU+8gQP#$}R7%4k6}9f~lzsJq+Ocq#d)_#R zr;l0FM58o~zR7bBC|LGf1DW2pQp>j?5JmqDSB{=b8NkP^$UAA9pxhBmA>&Bh>27?W z@c08NZTF&Vomn-o>N}$~YNJ1}TUIw?zJ~2J~Lg&53kgH!6dJ@rrU1Y4fO(Ru(mD&>Zgu(@xh_jt)YVit60o-=&@CG+_G z>O(GSVIR~~;88y*y48fC**2of6C~WMiw7+UhB(wxnNNqqCJm3ra0su25@- zp#eJ}uiF7aR*iY;@!>u%t;N(n!;N+M$ti@1|3TDc`NxqGKww!=xtAL73$sgmYWpkw zj5D>!Z!;JJwT*~wS%(kH*sY4!;c{OxOcK6}+o6uwR!wBnw!ZJZL&g-Zbs~Hisg0|- zj-B3&OFiE+!RrW%)W4|B6@-q|q?!A!YO|D5Dn9uh|p1G0%j6^H3ZnK|_8mv$X zYX0-h(xuf5q|6-Ac*mAxdxBrCdOolISc)LvnZg)dunbSe^K9-qV!Le!GpKgHffJ$9 z&gk`YZkZ=*;On#U!Tsx0wXn8(%Wu_r%QTYpzJOc}ikqfnSGxzZya2BRs1S!K zIvR5pr7Z~%?pR+v>WD{dWbltOjCM#B5V)Ve-&123%CSUt#$Y2K#j5im_=n69Tq9NQ z?Y@wF$;2}{M>seAGP(L?KT%P~4QoHM|oP6&iQLI2X`G(};+xBYpqsJR9rj!&!ov&gA z9ngXeAzzCmyu6q2`fCSC#PXtGPPRYlvd?9~Qs^`;pw#CW>QXzH2J_e06g9IbWA0`spQS>6Bs01e z`jJ?r8Yq+g4*)9ULcjLu2fnY!eK}ORaiyqEDxG$$r3ut`p?lLZyT`IRv0jB%>CC$tI}>2bjX;m3Y~H(9|&# zk8sL{(6fBJtoE%R&&aWo_#zhbG=1Z%lk5lYY8rlwG1SY678W=_`7w zzo)v>2onKu+K^uE8nxKob1^1W4X|F{*K`oGD(9B z*^y@Pj{zG@B@678A3P$Hq0)m4T2qI18uIgVhLbFyee^eKUYEBVX(aO;;n=t1&6(

    Kc<1gGvl3-~VveMBiP# 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 literal 0 HcmV?d00001 diff --git a/Read Me!.TXT b/Read Me!.TXT new file mode 100644 index 0000000..9fbc8af --- /dev/null +++ b/Read Me!.TXT @@ -0,0 +1 @@ +JPEGView Source Code Copyright ©1991-2001, Aaron Giles Author contact: mac@aarongiles.com This archive contains the full (I think) source code to JPEGView version 3.3, which was the last version I released back in 1994. I've gone through it a bit, but not thoroughly. If there is anything missing, or anything that shouldn't be included, please don't hesitate to contact me. There are various project files and other stuff included, but the final JPEGView was built on MPW with PPCC. A lot has changed since I wrote this code. Computers got way faster and memory got way cheaper. JPEGView began as the first Mac application I ever wrote and blossomed into something way beyond what I imagined. I still feel proud of this thing, though I cringe to look at some of my old source code. Maybe someone will find it useful still. SOFTWARE LICENSE This software is UNSUPPORTED. It is provided as-is, with no warranty implied or expressed. You may use this software only at your own risk; Aaron Giles is not responsible for any damage related to the use of this software. SOURCE CODE LICENSE The source code in this package is copyright ©1991-2001, Aaron Giles, unless otherwise attributed. It was written many years ago, so it likely will not compile as-is on much of anything. You may freely use small portions (up to 25%) of this software in your own code, as long as you acknowledge my copyright in your about box and documentation as follows: "Portions of this code ©1991-2001, Aaron Giles". I would also like to receive a copy/license to any software that makes use of my code. Contact me at the email above. If you wish to use larger portions of this code, you MUST contact me first, explaining what you are planning to do with it, in order to obtain permission. Under no circumstances may you release a variant of this software named Ð or obviously derived from the name Ð "JPEGView" without obtaining my permission to do so. \ No newline at end of file diff --git a/Resources/DialogHelpResources.r b/Resources/DialogHelpResources.r new file mode 100644 index 0000000..e957c18 --- /dev/null +++ b/Resources/DialogHelpResources.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #define SystemSevenOrLater 1 #include "SysTypes.r" #include "Types.r" #include "BalloonTypes.r" #include "JPEGView.r.h" #define dialogHelpOffset 1000 /***********************************************************************/ /************************ *************************/ /************************ Open Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rOpenDialog, purgeable) { HelpMgrVersion, 15, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rOpenDialog + dialogHelpOffset, 1, rOpenDialog + dialogHelpOffset, 2, 0, 0, 0, 0 } } }; resource 'STR#' (rOpenDialog + dialogHelpOffset, purgeable) { { "To scan for valid image files in the list of files above, click " "this button. If any valid images are found, their file types will be " "automatically corrected.", "Scans for valid image files in the list of files above. " "Not available because this folder has already been scanned." } }; /***********************************************************************/ /************************ *************************/ /************************ Save Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rSaveDialog, purgeable) { HelpMgrVersion, 12, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // Close when finished button { 0, 0 }, { 0, 0, 0, 0 }, rSaveDialog + dialogHelpOffset, 1, 0, 0, rSaveDialog + dialogHelpOffset, 2, 0, 0 }, hdlgBlankItem, // UserItem HMStringResItem { // PICT Button { 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, rSaveDialog + dialogHelpOffset, 3, rSaveDialog + dialogHelpOffset, 3 }, hdlgBlankItem, // UserItem HMStringResItem { // Create custom icons Button { 0, 0 }, { 0, 0, 0, 0 }, rSaveDialog + dialogHelpOffset, 4, 0, 0, rSaveDialog + dialogHelpOffset, 5, 0, 0 }, HMStringResItem { // Include preview/thumbnail Button { 0, 0 }, { 0, 0, 0, 0 }, rSaveDialog + dialogHelpOffset, 6, rSaveDialog + dialogHelpOffset, 7, rSaveDialog + dialogHelpOffset, 8, 0, 0 }, HMStringResItem { // Save quantized palette information Button { 0, 0 }, { 0, 0, 0, 0 }, rSaveDialog + dialogHelpOffset, 9, rSaveDialog + dialogHelpOffset, 10, rSaveDialog + dialogHelpOffset, 11, 0, 0 }, hdlgBlankItem, // UserItem HMStringResItem { // Use selection popup menu { 0, 0 }, { 0, 0, 0, 0 }, rSaveDialog + dialogHelpOffset, 12, rSaveDialog + dialogHelpOffset, 13, rSaveDialog + dialogHelpOffset, 12, 0, 0 } } }; resource 'STR#' (rSaveDialog + dialogHelpOffset, purgeable) { { "To automatically close the image after it has been successfully saved, " "click this box.", "The image will automatically be closed after it has been successfully " "saved. To leave the image open, click this box.", "Use this pop-up menu to select the file format you wish to save this image in. ", "To request custom icons for the new image file, click this box. Custom " "icons, which can be seen in the Finder, serve as miniature previews of " "the image file contents.", "Custom icons will be created for the new image file. To save the image " "with generic JPEGView icons, click this box.", "To request a preview (aka thumbnail) for the new image file, click this " "box. Previews can be seen in any QuickTime-based Open dialog, " "including the one in JPEGView.", "Creates a preview (aka thumbnail) for the new image file. Not available " "because JPEGView needs QuickTime installed before it can create previews.", "A preview (aka thumbnail) will be created for the new image file. To save " "the image without a preview, click this box.", "To request that a reduced color set be saved with the new image file, " "click this box. A reduced color set allows images to be opened " "quickly, without waiting for two-pass color reduction.", "Saves a reduced color set with the new image file. Not available because " "this information can only be included in a JPEG-compressed PICT or JFIF file.", "A reduced color set will be saved with the new image file. To request " "that this color set not be saved, click this box.", "Use this popup menu to specify what you would like to use the currently selected " "area of the image for.", "Use this popup menu to specify what you would like to use the currently selected " "area of the image for. Not available because you didnÕt select anything in " "the image before you chose to save." } }; /***********************************************************************/ /************************ *************************/ /************************ Folder Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rFolderDialog, purgeable) { HelpMgrVersion, 14, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // Select Folder Button { 0, 0 }, { 0, 0, 0, 0 }, rFolderDialog + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rFolderDialog + dialogHelpOffset, purgeable) { { "To select the displayed folder for the slide show, click this button." } }; /***********************************************************************/ /************************ *************************/ /************************ Slide Show Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rSlideShowDialog, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // Begin Button { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 1, rSlideShowDialog + dialogHelpOffset, 2, 0, 0, 0, 0 }, hdlgBlankItem, // UserItem HMStringResItem { // Revert Button { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 3, 0, 0, 0, 0, 0, 0 }, hdlgBlankItem, // delay text HMStringResItem { // EditText box { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 4, rSlideShowDialog + dialogHelpOffset, 5, 0, 0, 0, 0 }, HMStringResItem { // Units pop-up menu { 0, 0 }, { 0, 0, 0, 0 }, 0, 0, rSlideShowDialog + dialogHelpOffset, 6, rSlideShowDialog + dialogHelpOffset, 7, rSlideShowDialog + dialogHelpOffset, 7 }, HMStringResItem { // Display in random order checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 8, 0, 0, rSlideShowDialog + dialogHelpOffset, 9, 0, 0 }, HMStringResItem { // Repeat indefinitely checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 10, 0, 0, rSlideShowDialog + dialogHelpOffset, 11, 0, 0 }, HMStringResItem { // Ignore any non-fatal errors checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 12, 0, 0, rSlideShowDialog + dialogHelpOffset, 13, 0, 0 }, HMStringResItem { // Hide floating windows checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 14, 0, 0, rSlideShowDialog + dialogHelpOffset, 15, 0, 0 }, HMStringResItem { // Hide slide show controls checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 16, 0, 0, rSlideShowDialog + dialogHelpOffset, 17, 0, 0 }, HMStringResItem { // Automatic comments control checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 18, 0, 0, rSlideShowDialog + dialogHelpOffset, 19, 0, 0 }, HMStringResItem { // Display filenames checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 20, rSlideShowDialog + dialogHelpOffset, 21, rSlideShowDialog + dialogHelpOffset, 22, 0, 0 }, HMStringResItem { // Slide show control menu { 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, rSlideShowDialog + dialogHelpOffset, 23, rSlideShowDialog + dialogHelpOffset, 23 }, hdlgBlankItem, // outline box HMStringResItem { // Select slide show folder button { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 24, rSlideShowDialog + dialogHelpOffset, 25, 0, 0, 0, 0 }, HMStringResItem { // UserItem { 0, 0 }, { -20, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 26, rSlideShowDialog + dialogHelpOffset, 26, 0, 0, 0, 0 }, HMStringResItem { // Scan subfolders recursively checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 27, rSlideShowDialog + dialogHelpOffset, 28, rSlideShowDialog + dialogHelpOffset, 29, 0, 0 }, HMStringResItem { // Import unrecognized files checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 30, rSlideShowDialog + dialogHelpOffset, 31, rSlideShowDialog + dialogHelpOffset, 32, 0, 0 }, HMStringResItem { // Render offscreen before display checkbox { 0, 0 }, { 0, 0, 0, 0 }, rSlideShowDialog + dialogHelpOffset, 33, rSlideShowDialog + dialogHelpOffset, 34, rSlideShowDialog + dialogHelpOffset, 35, 0, 0 }, HMStringResItem { // Slide source menu { 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, rSlideShowDialog + dialogHelpOffset, 36, rSlideShowDialog + dialogHelpOffset, 36 } } }; resource 'STR#' (rSlideShowDialog + dialogHelpOffset, purgeable) { { "To save the changes you made and begin the slide show, click this button.", "Saves the changes you made and begins the slide show. Not available " "either because there are no open images for a memory-based slide show, " "or because you have not selected a valid disk folder.", "To restore the settings to what you had previously, click this button.", "Type the number of seconds, minutes, or hours JPEGView should delay " "between images here.", "Type the number of seconds, minutes, or hours JPEGView should delay " "between images. Not available because you have selected a user-" "controlled slide show.", "Use this pop-up menu to specify the units of time entered in the box to " "the left. Not available because you have selected a user-controlled " "slide show.", "Use this pop-up menu to specify the units of time entered in the box to " "the left.", "To automatically shuffle the order of the slides before each repetition, " "click this box.", "The order of the slides will be automatically shuffled before each " "repetition. To display the slides in the order they are found, click " "this box.", "To repeat the slide show over and over until it is explicitly interrupted, " "check this box.", "The slide show will repeat over and over until it is explicitly " "interrupted. To end the slide show after the first pass through your " "slides, click this box.", "To ignore any minor errors that occur during the slide show, click this " "box.", "Any minor errors that occur during the slide show will be ignored. To " "report all errors during the slide show, check this box.", "To automatically hide all visible floating windows for the duration of the " "slide show, click this box.", "All visible floating windows will be hidden for the duration of the slide " "show. To keep the floating windows open during the slide show, click " "this box.", "To keep the slide show controls window hidden when the slide show starts, " "click this box.", "The slide show controls window will be invisible when the slide show starts. " "To ensure that the controls are visible from the beginning of the slide " "show, click this box.", "To automatically display the Comments floating window whenever image " "comments are found, click this box.", "The Comments floating window will be automatically displayed whenever " "image comments are found. To leave the Comments floating window " "alone, click this box.", "To display the name of each file in the bottom-right corner of the image, " "click this box.", "Displays the name of each file in the bottom-right corner of the image. " "Not available because you have selected a slide show from images in " "memory.", "Displays the name of each file in the bottom-right corner of the image. To " "prevent the names from being displayed, click this box.", "Use this pop-up menu to select either a user-controlled slide show or an " "automatic slide show.", "To choose the folder from which the slide show images will be selected, " "click this button.", "Allows you to choose the folder from which the slide show images " "will be selected. Not available because you have selected a " "slide show from images in memory.", "This is the folder from which a disk-based slide show will be run.", "To scan not only the folder selected above, but also all enclosed folders, " "click this box.", "Scans not only the folder selected above, but also all enclosed folders. " "Not available because you have selected a slide show from images in " "memory.", "The folder selected above will be scanned, in addition to all enclosed " "folders, for slide show images. To prevent any enclosed folders from " "being scanned, click this box.", "To read every file in the selected folder, regardless of what type the " "Finder says it is, click this box.", "Reads every file in the selected folder, regardless of what type the " "Finder says it is. Not available because you have selected a slide " "show from images in memory.", "Every file in the selected folder will be read, regardless of what type " "the Finder says it is. To only read files which the Finder says are " "valid, click this box.", "To draw the next image offscreen before removing the current image, click " "this box. This option minimizes the transition time between slides, " "but may cause long delays between slides.", "Draws the next image offscreen before removing the current image. Not " "available because you have selected a slide show from images in memory.", "The next image will be drawn offscreen before removing the current image. " "To draw the next image as soon as it is loaded into memory, click this " "box.", "Use this pop-up menu to select whether the slide show images should come " "from those currently in memory or from a folder on a disk." } }; /***********************************************************************/ /************************ *************************/ /************************ Preferences Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rPrefsDialog, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { hdlgBlankItem, // StaticText HMStringResItem { // Deepest screen button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 1, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 2, 0, 0 }, HMStringResItem { // Largest screen button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 3, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 4, 0, 0 }, HMStringResItem { // Main screen button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 5, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 6, 0, 0 }, HMStringResItem { // Pick color over B&W checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 7, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 8, 0, 0 }, hdlgBlankItem, // StaticText HMStringResItem { // Always button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 9, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 10, 0, 0 }, HMStringResItem { // Always for large images button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 11, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 12, 0, 0 }, HMStringResItem { // Ask first for large images button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 13, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 14, 0, 0 }, HMStringResItem { // Never button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 15, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 16, 0, 0 }, HMStringResItem { // Expand small images checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 17, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 18, 0, 0 }, HMStringResItem { // Only one image checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 901, 19, 0, 0, rPrefsDialog + dialogHelpOffset + 901, 20, 0, 0 }, hdlgBlankItem, // StaticText HMStringResItem { // V. High quality button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 1, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 2, 0, 0 }, HMStringResItem { // High quality button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 3, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 4, 0, 0 }, HMStringResItem { // Medium quality button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 5, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 6, 0, 0 }, HMStringResItem { // Never update background windows checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 7, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 8, 0, 0 }, hdlgBlankItem, // StaticText HMStringResItem { // Always button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 9, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 10, 0, 0 }, HMStringResItem { // Only if no internal palette button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 11, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 12, 0, 0 }, HMStringResItem { // Never button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 13, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 14, 0, 0 }, HMStringResItem { // Dither quantized images checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 15, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 16, 0, 0 }, HMStringResItem { // Use internal palette for other images { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 17, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 18, 0, 0 }, HMStringResItem { // Restore colors after last close checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 902, 19, 0, 0, rPrefsDialog + dialogHelpOffset + 902, 20, 0, 0 }, hdlgBlankItem, // StaticText HMStringResItem { // Always button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 903, 1, 0, 0, rPrefsDialog + dialogHelpOffset + 903, 2, 0, 0 }, HMStringResItem { // Optional button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 903, 3, 0, 0, rPrefsDialog + dialogHelpOffset + 903, 4, 0, 0 }, HMStringResItem { // Never button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 903, 5, 0, 0, rPrefsDialog + dialogHelpOffset + 903, 6, 0, 0 }, HMStringResItem { // Maintain bitmaps at original size checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 903, 7, 0, 0, rPrefsDialog + dialogHelpOffset + 903, 8, 0, 0 }, HMStringResItem { // DonÕt create bitmaps for uncompressed images { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 903, 9, 0, 0, rPrefsDialog + dialogHelpOffset + 903, 10, 0, 0 }, HMStringResItem { // Automatically fix incorrect file types checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 1, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 2, 0, 0 }, HMStringResItem { // Fix creators as well checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 3, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 4, 0, 0 }, hdlgBlankItem, // StaticText HMStringResItem { // Always button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 5, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 6, 0, 0 }, HMStringResItem { // Only if no other palette button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 7, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 8, 0, 0 }, HMStringResItem { // Only if no other palette button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 9, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 10, 0, 0 }, HMStringResItem { // Use PICT format by default checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 11, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 12, 0, 0 }, HMStringResItem { // Save previews checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 13, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 14, 0, 0 }, HMStringResItem { // Compress preview images checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 15, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 16, 0, 0 }, HMStringResItem { // Create icons checkbox { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 904, 17, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 18, 0, 0 }, HMStringResItem { // Icon style popup menu { 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, rPrefsDialog + dialogHelpOffset + 904, 19, rPrefsDialog + dialogHelpOffset + 904, 19 }, hdlgBlankItem, // StaticText HMStringResItem { // Begin slide show button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 1, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 2, 0, 0 }, HMStringResItem { // Slide show options dialog button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 3, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 4, 0, 0 }, HMStringResItem { // Open dialog button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 5, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 6, 0, 0 }, HMStringResItem { // Nothing button { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 7, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 8, 0, 0 }, HMStringResItem { // Automatic comments window control { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 9, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 10, 0, 0 }, hdlgBlankItem, // StaticText HMStringResItem { // Maximal time to BG apps { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 11, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 12, 0, 0 }, HMStringResItem { // Reasonable time to BG apps { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 13, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 14, 0, 0 }, HMStringResItem { // Minimal time to BG apps { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 15, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 16, 0, 0 }, HMStringResItem { // Use QuickTime to decompress JPEGs { 0, 0 }, { 0, 0, 0, 0 }, rPrefsDialog + dialogHelpOffset + 905, 17, 0, 0, rPrefsDialog + dialogHelpOffset + 905, 18, 0, 0 }, HMStringResItem { // Pop-up menu { 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, rPrefsDialog + dialogHelpOffset + 900, 1, rPrefsDialog + dialogHelpOffset + 900, 1 } } }; resource 'STR#' (rPrefsDialog + dialogHelpOffset + 900, purgeable) { { "Use this pop-up menu to access other groups of options." } }; resource 'STR#' (rPrefsDialog + dialogHelpOffset + 901, purgeable) { { "To open new images on the screen that can display the most colors, click " "this button. This will give the highest-quality color fidelity for " "the image.", "Opens new images on the screen that can display the most colors. This " "option is selected.", "To open new images on the screen that has the largest area in pixels, " "click this button. This will allow images to be displayed at the " "largest possible size.", "Opens new images on the screen that has the largest area in pixels. This " "option is selected.", "To open new images on the screen that has the menubar, click this button. " "This will keep all image windows near the menus, for quicker access.", "Opens new images on the screen that has the menubar. This option is " "selected.", "To ask that color screens be chosen over B&W/grayscale screens with similar " "characteristics, click this box.", "Color screens will be chosen over B&W/grayscale screens with similar " "characteristics. To ask that B&W/grayscale screens be chosen over " "color screens instead, click this box.", "To open all images in a full-screen window, regardless of their size, " "click this button.", "Opens all images in a full-screen window, regardless of their size. This " "option is selected.", "To automatically open images taller than the screen in a full-screen " "window without asking, click this button.", "Automatically opens images taller than the screen in a full-screen " "window without asking. This option is selected.", "To request that you be asked before opening images taller than the screen " "in a full-screen window, click this button.", "Asks before opening images taller than the screen in a full-screen window. " "This option is selected.", "To always open images in a normal window, even if they would benefit from " "being displayed in a full-screen window, click this box.", "Always opens images in a normal window, even if they would benefit from " "being displayed in a full-screen window, click this box. This option " "is selected.", "To automatically expand smaller images to their maximum size on the " "preferred screen, click this box.", "Smaller images are automatically expanded to their maximum size on the " "preferred screen. To keep small images at their natural size, click " "this box.", "To automatically close all other open images before opening a new image, " "click this box. This helps reduce clutter on the desktop.", "All other open images will be automatically closed before opening a new " "image. To keep multiple images open at once, click this box." } }; resource 'STR#' (rPrefsDialog + dialogHelpOffset + 902, purgeable) { { "To display images using Òvery highÓ quality, click this button. This " "option only affects images displayed on screens with 256 or more " "colors.", "Displays images using Òvery highÓ quality. This option is selected.", "To display images using ÒhighÓ quality, click this button. This " "option only affects images displayed on screens with 256 or more " "colors.", "Displays images using ÒhighÓ quality. This option is selected.", "To display images using ÒnormalÓ quality, click this button. This " "option only affects images displayed on screens with 256 or more " "colors.", "Displays images using ÒnormalÓ quality. This option is selected.", "To prevent slow window updates, when necessary, from being used in windows " "behind the active window, click this box.", "Slow window updates, when necessary, will only be used in the active " "window. To allow slow window updates in other windows after five " "seconds of idle time, click this box.", "To perform two-pass color reduction on any applicable image, click this " "box. Only images with Thousands or more colors will be reduced, and " "then only to 16 or 256 colors.", "Performs two-pass color reduction on any applicable image. This " "option is selected.", "To perform two-pass color reduction only on images that have no image " "colors defined, click this button. Only images with Thousands or more " "colors will be reduced, and then only to 16 or 256 colors.", "Performs two-pass color reduction only on images that have no image " "colors defined. This option is selected.", "To prevent two-pass color reduction from being used at all, click this " "box.", "Prevents two-pass color reduction from being used. This option is " "selected.", "To use dithering when displaying images on 256 color displays with " "two-pass color reduction, click this box.", "Dithering will be used when displaying images on 256 color displays with " "two-pass color reduction. To turn off dithering in this situation, " "click this box.", "To automatically use the imageÕs colors if present, click this box.", "The imageÕs colors will automatically be used, if present. To use the " "standard set of Finder colors instead, click this box.", "To restore the system colors on all monitors whenever the last image is " "closed, check this box.", "The system colors will be restored on all monitors whenever the last image " "is closed. To leave the colors alone after closing the last image, " "click this box." } }; resource 'STR#' (rPrefsDialog + dialogHelpOffset + 903, purgeable) { { "To make offscreen bitmaps a requirement for all images, click this button. " "This helps ensure that all image windows will be updated quickly.", "Makes offscreen bitmaps a requirement for all images. This option is " "selected.", "To make offscreen bitmaps optional, click this button. This allows you to " "enjoy the benefits of fast updates when enough memory is available.", "Makes offscreen bitmaps optional. This option is selected.", "To prevent offscreen bitmaps from being used, click this button. This " "means that you will never see the benefits fast window updates.", "Prevents offscreen bitmaps from being used. This option is selected.", "To maintain bitmaps at the imageÕs original size, click this box. Original " "size bitmaps require more memory and slow down drawing, but speed up " "image manipulation.", "Offscreen bitmaps will be maintained at the imageÕs original size. To " "reduce the size of offscreen bitmaps and to speed up drawing, check " "this box.", "To prevent the use of offscreen bitmaps for images that are not compressed, " "check this box.", "Offscreen bitmaps will not be used for images that are not compressed. To " "create offscreen bitmaps for any kind of image, compressed or not, " "click this box." } }; resource 'STR#' (rPrefsDialog + dialogHelpOffset + 904, purgeable) { { "To quietly fix incorrect file types on any files you open in JPEGView, " "click this box. This ensures proper identification of the image by " "the Finder and other applications.", "Incorrect file types are automatically fixed when you open a file in " "JPEGView. To prevent this from happening behind your back, click this " "box.", "To make JPEGView the owner of any files whose types are automatically " "fixed, click this box. This means that the Finder will open JPEGView " "when you double-click on the fileÕs icon.", "JPEGView will become the owner of any files whose types are automatically " "fixed. To retain the fileÕs original owner, click this box.", "To automatically turn on the ÒSave reduced color setÓ option when saving " "images that have been previously reduced, click this button.", "Automatically turns on the ÒSave reduced color setÓ option when saving " "images that have been previously reduced. This option is selected.", "To turn on the ÒSave reduced color setÓ option only when saving images " "that have no image colors, click this button.", "Turns on the ÒSave reduced color setÓ option only when saving images that " "have no image colors. This option is selected.", "To always leave the ÒSave reduced color setÓ option off when saving " "images, click this button.", "Leaves the ÒSave reduced color setÓ option off when saving images. This " "option is selected.", "To automatically set the output file type to PICT when saving an image, " "regardless of which format the image was originally stored in, click " "this box.", "The output file type will automatically be set to PICT when saving an " "image. To keep the file format the same as it originally was, click " "this box.", "To automatically turn on the ÒInclude preview imageÓ option when saving " "PICT and JFIF images, click this box.", "The ÒInclude preview imageÓ option will automatically be turned on when " "saving PICT and JFIF images. To leave the previews option off, click " "this box.", "To compress previews created when saving JFIF images, click this box. " "This saves space in the JFIF file at the expense of the previewÕs " "image quality.", "Previews created when saving JFIF images will be compressed. To leave " "previews uncompressed, click this box.", "To automatically turn on the ÒCreate custom iconsÓ option when saving " "images, click this box.", "The ÒCreate custom iconsÓ option will be automatically turned on when " "saving images. To leave the custom icons option off, click this box.", "Use this pop-up menu to select the icon style you prefer." } }; resource 'STR#' (rPrefsDialog + dialogHelpOffset + 905, purgeable) { { "To automatically start up the slide show with the last set of saved " "settings, click this button.", "Automatically starts up the slide show with the last set of saved " "settings. This option is selected.", "To bring up the Slide Show Options dialog when JPEGView starts, click " "this button.", "Brings up the Slide Show Options dialog when JPEGView starts. This option " "is selected.", "To bring up the Open dialog when JPEGView starts, click this button.", "Brings up the Open dialog when JPEGView starts. This option is selected.", "To do nothing when JPEGView starts, click this button.", "Does nothing when JPEGView starts. This option is selected.", "To automatically display the Comments floating window whenever the active " "image contains comments, click this box.", "The Comments floating window will automatically be displayed whenever the " "active image contains comments. To leave the comments under user " "control, click this box.", "To give other applications a lot of processor time while JPEGView is " "decompressing images, click this button. This option will certainly " "slow down JPEGViewÕs operations.", "Gives other applications a lot of processor time while JPEGView is " "decompressing images. This option is selected.", "To give other applications a reasonable amount of processor time while " "JPEGView is decompressing images, click this button.", "Gives other applications a reasonable amount of processor time while " "JPEGView is decompressing images. This option is selected.", "To give other applications very little processor time while JPEGView is " "decompressing images, click this button. This option will cause " "other applications to slow down greatly.", "Gives other applications very little processor time while JPEGView is " "decompressing images. This option is selected.", "To use QuickTime for displaying JPEG-compressed images, check this box. " "On non-PowerPC Macintoshes, this option usually speeds up JPEG " "decompression.", "To use the Independent JPEG GroupÕs (IJG) code for decompressing JPEG images, " "uncheck this box. The IJG code is more robust and less prone to " "crashing on damaged JPEG images." } }; /***********************************************************************/ /************************ *************************/ /************************ Minor Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rMinorAlert, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // OK Button { 0, 0 }, { 0, 0, 0, 0 }, rMinorAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rMinorAlert + dialogHelpOffset, purgeable) { { "To continue, click this button." } }; /***********************************************************************/ /************************ *************************/ /************************ Fatal Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rFatalAlert, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // OK Button { 0, 0 }, { 0, 0, 0, 0 }, rFatalAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rFatalAlert + dialogHelpOffset, purgeable) { { "To return to the Finder, click this button. There is no way to return " "to JPEGView without starting over." } }; /***********************************************************************/ /************************ *************************/ /************************ Unknown Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rUnknownAlert, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // OK Button { 0, 0 }, { 0, 0, 0, 0 }, rUnknownAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rUnknownAlert + dialogHelpOffset, purgeable) { { "To continue, click this button. Please report this error to the author " "as soon as possible. In the meantime, proceed with caution." } }; /***********************************************************************/ /************************ *************************/ /************************ End Slides Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rEndSlidesAlert, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // OK Button { 0, 0 }, { 0, 0, 0, 0 }, rEndSlidesAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rEndSlidesAlert + dialogHelpOffset, purgeable) { { "To return to JPEGViewÕs normal mode of operations, click this button." } }; /***********************************************************************/ /************************ *************************/ /************************ Slide Memory Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rSlideMemAlert, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // Continue Button { 0, 0 }, { 0, 0, 0, 0 }, rSlideMemAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 }, hdlgBlankItem, // Static text HMStringResItem { // Abort Button { 0, 0 }, { 0, 0, 0, 0 }, rSlideMemAlert + dialogHelpOffset, 2, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rSlideMemAlert + dialogHelpOffset, purgeable) { { "To proceed, even though the slide show will be incomplete, click this " "button.", "To abort the slide show immediately, click this button." } }; /***********************************************************************/ /************************ *************************/ /************************ Too Big Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rTooBigAlert, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // Yes Button { 0, 0 }, { 0, 0, 0, 0 }, rTooBigAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 }, hdlgBlankItem, // Static text HMStringResItem { // No Button { 0, 0 }, { 0, 0, 0, 0 }, rTooBigAlert + dialogHelpOffset, 2, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rTooBigAlert + dialogHelpOffset, purgeable) { { "To use a full-screen window for the image, click this button.", "To resort to a standard-size window for the image, click this button." } }; /***********************************************************************/ /************************ *************************/ /************************ Bad JPEG Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'hdlg' (rBadJPEGAlert, purgeable) { HelpMgrVersion, 0, hmDefaultOptions, 0, 0, hdlgBlankItem, // Defaults { HMStringResItem { // OK Button { 0, 0 }, { 0, 0, 0, 0 }, rBadJPEGAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 }, hdlgBlankItem, // Static text HMStringResItem { // Cancel Button { 0, 0 }, { 0, 0, 0, 0 }, rBadJPEGAlert + dialogHelpOffset, 1, 0, 0, 0, 0, 0, 0 } } }; resource 'STR#' (rBadJPEGAlert + dialogHelpOffset, purgeable) { { "To proceed with viewing the image, click this button.", "To abort the viewing of the image, click this button." } }; \ No newline at end of file diff --git a/Resources/DialogResources.r b/Resources/DialogResources.r new file mode 100644 index 0000000..810e7b3 --- /dev/null +++ b/Resources/DialogResources.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #define SystemSevenOrLater 1 #include "SysTypes.r" #include "Types.r" #include "BalloonTypes.r" #include "JPEGView.r.h" #define dialogHelpOffset 1000 /***********************************************************************/ /************************ *************************/ /************************ Open Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rOpenDialog, preload) { { 0, 0, 208, 447 }, dBoxProc, invisible, noGoAway, kOpenDialogID, rOpenDialog, "", noAutoCenter }; resource 'dctb' (rOpenDialog, preload) { { }, { } }; resource 'DITL' (rOpenDialog, preload) { { { 135, 355, 155, 435 }, Button { enabled, "Open" }, { 104, 355, 124, 435 }, Button { enabled, "Cancel" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { -6042 } }, { 8, 340, 24, 442 }, UserItem { enabled }, { 32, 355, 52, 435 }, Button { enabled, "Eject" }, { 60, 355, 80, 435 }, Button { enabled, "Desktop" }, { 29, 118, 159, 336 }, UserItem { enabled }, { 6, 118, 25, 336 }, UserItem { enabled }, { 91, 354, 92, 436 }, Picture { disabled, 11 }, { 1043, 122, 1144, 218 }, StaticText { disabled, "" }, { 39, 5, 139, 105 }, UserItem { enabled }, { 18, 27, 34, 84 }, StaticText { disabled, "Preview" }, { 29, 110, 174, 111 }, UserItem { disabled }, { 143, 15, 163, 95 }, Button { enabled, "Create" }, { 161, 118, 181, 234 }, CheckBox { enabled, "Show Preview" }, { 184, 118, 204, 336 }, Button { enabled, "Scan for Image Files" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rOpenDialog } } } }; /***********************************************************************/ /************************ *************************/ /************************ Small Open Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rOpenDialogNoQT, preload) { { 0, 0, 188, 344 }, dBoxProc, invisible, noGoAway, kOpenDialogID, rOpenDialogNoQT, "", noAutoCenter }; resource 'dctb' (rOpenDialogNoQT, preload) { { }, { } }; resource 'DITL' (rOpenDialogNoQT, preload) { { { 135, 252, 155, 332 }, Button { enabled, "Open" }, { 104, 252, 124, 332 }, Button { enabled, "Cancel" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { -6042 } }, { 8, 235, 24, 337 }, UserItem { enabled }, { 32, 252, 52, 332 }, Button { enabled, "Eject" }, { 60, 252, 80, 332 }, Button { enabled, "Desktop" }, { 29, 12, 159, 230 }, UserItem { enabled }, { 6, 12, 25, 230 }, UserItem { enabled }, { 91, 251, 92, 333 }, Picture { disabled, 11 }, { 1043, 122, 1144, 218 }, StaticText { disabled, "" }, { 1039, 5, 1139, 105 }, UserItem { disabled }, { 1018, 27, 1034, 84 }, StaticText { disabled, "Preview" }, { 1029, 110, 1174, 111 }, UserItem { disabled }, { 1143, 15, 1163, 95 }, Button { disabled, "Create" }, { 1161, 118, 1181, 234 }, CheckBox { disabled, "Show Preview" }, { 164, 15, 184, 233 }, Button { enabled, "Scan for Image Files" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rOpenDialog } } } }; /***********************************************************************/ /************************ *************************/ /************************ Save Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rSaveDialog, preload) { { 0, 0, 326, 344 }, dBoxProc, invisible, noGoAway, kSaveDialogID, rSaveDialog, "", noAutoCenter }; resource 'CNTL' (rSavePopupControl, preload) { { 208, 9, 228, 310 }, popupTitleRightJust, visible, 150, rSaveMenu, popupMenuCDEFProc + popupFixedWidth, 0, "Output file format: " }; resource 'CNTL' (rCropPopupControl, preload) { { 302, 9, 322, 285 }, popupTitleRightJust, visible, 175, rCropMenu, popupMenuCDEFProc + popupFixedWidth, 0, "Use selection to crop: " }; resource 'dctb' (rSaveDialog, preload) { { }, { } }; resource 'DITL' (rSaveDialog, preload) { { { 161, 252, 181, 332 }, Button { enabled, "Save" }, { 130, 252, 150, 332 }, Button { enabled, "Cancel" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { -6043 } }, { 8, 235, 24, 337 }, UserItem { enabled }, { 32, 252, 52, 332 }, Button { enabled, "Eject" }, { 60, 252, 80, 332 }, Button { enabled, "Desktop" }, { 29, 12, 127, 230 }, UserItem { enabled }, { 6, 12, 25, 230 }, UserItem { enabled }, { 119, 250, 120, 334 }, Picture { disabled, 11 }, { 157, 15, 173, 227 }, EditText { enabled, "" }, { 136, 15, 152, 227 }, StaticText { disabled, "Save as:" }, { 88, 252, 108, 332 }, UserItem { disabled }, { 180, 42, 198, 198 }, CheckBox { enabled, "Close when finished" }, { 201, 9, 202, 333 }, UserItem { disabled }, { 208, 9, 228, 310 }, Control { enabled, rSavePopupControl }, { 233, 9, 234, 333 }, UserItem { disabled }, { 237, 42, 255, 298 }, CheckBox { enabled, "Create custom Finder icons" }, { 255, 42, 273, 298 }, CheckBox { enabled, "Create QuickTime preview" }, { 273, 42, 291, 298 }, CheckBox { enabled, "Remember reduced color set" }, { 294, 9, 295, 333 }, UserItem { disabled }, { 301, 9, 321, 285 }, Control { enabled, rCropPopupControl }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rSaveDialog } } } }; /***********************************************************************/ /************************ *************************/ /************************ Simple Save Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rSimpleSaveDialog, preload) { { 0, 0, 294, 344 }, dBoxProc, invisible, noGoAway, kSaveDialogID, rSimpleSaveDialog, "", noAutoCenter }; resource 'dctb' (rSimpleSaveDialog, preload) { { }, { } }; resource 'DITL' (rSimpleSaveDialog, preload) { { { 161, 252, 181, 332 }, Button { enabled, "Save" }, { 130, 252, 150, 332 }, Button { enabled, "Cancel" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { -6043 } }, { 8, 235, 24, 337 }, UserItem { enabled }, { 32, 252, 52, 332 }, Button { enabled, "Eject" }, { 60, 252, 80, 332 }, Button { enabled, "Desktop" }, { 29, 12, 127, 230 }, UserItem { enabled }, { 6, 12, 25, 230 }, UserItem { enabled }, { 119, 250, 120, 334 }, Picture { disabled, 11 }, { 157, 15, 173, 227 }, EditText { enabled, "" }, { 136, 15, 152, 227 }, StaticText { disabled, "Save as:" }, { 88, 252, 108, 332 }, UserItem { disabled }, { 180, 42, 198, 198 }, CheckBox { enabled, "Close when finished" }, { 201, 9, 202, 333 }, UserItem { disabled }, { 1208, 1009, 1228, 1310 }, Control { enabled, rSavePopupControl }, { 1232, 1009, 1233, 1333 }, UserItem { disabled }, { 205, 42, 223, 298 }, CheckBox { enabled, "Create custom Finder icons" }, { 223, 42, 241, 298 }, CheckBox { enabled, "Create QuickTime preview" }, { 241, 42, 259, 298 }, CheckBox { enabled, "Remember reduced color set" }, { 262, 9, 263, 333 }, UserItem { disabled }, { 269, 9, 289, 285 }, Control { enabled, rCropPopupControl }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rSaveDialog } } } }; /***********************************************************************/ /************************ *************************/ /************************ Folder Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rFolderDialog, preload) { { 0, 0, 215, 344 }, dBoxProc, invisible, noGoAway, kFolderDialogID, rFolderDialog, "", noAutoCenter }; resource 'dctb' (rFolderDialog, preload) { { }, { } }; resource 'DITL' (rFolderDialog, preload) { { { 157, 253, 177, 333 }, Button { enabled, "Open" }, { 126, 253, 146, 333 }, Button { enabled, "Cancel" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { -6042 } }, { 30, 236, 46, 338 }, UserItem { enabled }, { 54, 253, 74, 333 }, Button { enabled, "Eject" }, { 82, 253, 102, 333 }, Button { enabled, "Desktop" }, { 51, 13, 181, 231 }, UserItem { enabled }, { 28, 13, 47, 231 }, UserItem { enabled }, { 113, 252, 114, 334 }, Picture { disabled, 11 }, { 1157, 1015, 1173, 1227 }, StaticText { disabled, "" }, { 1136, 1015, 1152, 1227 }, StaticText { disabled, "Save as:" }, { 1088, 1252, 1108, 1332 }, UserItem { disabled }, { 189, 24, 209, 211 }, Button { enabled, "" }, { 6, 15, 23, 128 }, StaticText { disabled, "Select a folder:" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rFolderDialog } } } }; /***********************************************************************/ /************************ *************************/ /************************ Slide Show Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rSlideShowDialog, preload) { { 0, 0, 232, 510 }, noGrowDocProc, invisible, goAway, kSlideShowDialogID, rSlideShowDialog, "JPEGView Slide Show Options", noAutoCenter }; resource 'dctb' (rSlideShowDialog, preload) { { }, { } }; resource 'CNTL' (rSlideControlMenuControl, preload) { { 13, 30, 33, 200 }, popupTitleLeftJust, visible, 0, rSlideControlMenu, popupMenuCDEFProc + popupFixedWidth, 0, "" }; resource 'CNTL' (rSlideSourceMenuControl, preload) { { 13, 272, 33, 452 }, popupTitleLeftJust, visible, 0, rSlideSourceMenu, popupMenuCDEFProc + popupFixedWidth, 0, "" }; resource 'CNTL' (rTimeMenuControl, preload) { { 43, 130, 63, 225 }, popupTitleLeftJust, visible, 0, rTimeMenu, popupMenuCDEFProc, 0, "" }; resource 'DITL' (rSlideShowDialog, preload) { { { 194, 417, 214, 492 }, Button { enabled, "Begin" }, { 189, 412, 219, 497 }, UserItem { disabled }, { 194, 332, 214, 407 }, Button { enabled, "Revert" }, { 45, 23, 61, 70 }, StaticText { disabled, "Delay:" }, { 45, 80, 61, 120 }, EditText { enabled, "15" }, { 43, 130, 63, 225 }, Control { enabled, rTimeMenuControl }, { 83, 13, 101, 245 }, CheckBox { enabled, "Display in random order" }, { 101, 13, 119, 245 }, CheckBox { enabled, "Repeat indefinitely" }, { 119, 13, 137, 245 }, CheckBox { enabled, "Ignore minor errors" }, { 147, 13, 165, 245 }, CheckBox { enabled, "Hide floating windows" }, { 165, 13, 183, 245 }, CheckBox { enabled, "Hide slide show controls" }, { 183, 13, 201, 245 }, CheckBox { enabled, "Automatically show comments" }, { 201, 13, 219, 245 }, CheckBox { enabled, "Display filenames" }, { 13, 30, 33, 200 }, Control { enabled, rSlideControlMenuControl }, { 23, 13, 73, 245 }, UserItem { disabled }, { 43, 265, 63, 487 }, Button { enabled, "Select Slide Show FolderÉ" }, { 73, 265, 91, 487 }, UserItem { disabled }, { 101, 265, 119, 487 }, CheckBox { enabled, "Scan subfolders recursively" }, { 119, 265, 137, 487 }, CheckBox { enabled, "Import unrecognized files" }, { 137, 265, 155, 487 }, CheckBox { enabled, "Decompress offscreen" }, { 13, 272, 33, 452 }, Control { enabled, rSlideSourceMenuControl }, { 23, 255, 165, 497 }, UserItem { disabled }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rSlideShowDialog } } } }; /***********************************************************************/ /************************ *************************/ /************************ Preferences Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rPrefsDialog, preload) { { 0, 0, 309, 396 }, noGrowDocProc, invisible, goAway, kPrefsDialogID, rPrefsDialog, "JPEGView Preferences", noAutoCenter }; resource 'CNTL' (rPrefsMenuControl, preload) { { 13, 30, 33, 203 }, popupTitleLeftJust, visible, 0, rPrefsMenu, popupMenuCDEFProc + popupFixedWidth, 0, "" }; resource 'CNTL' (rIconPopupControl, preload) { { 13, 23, 53, 373 }, popupTitleLeftJust, visible, 100, rIconMenu, popupMenuCDEFProc + popupFixedWidth, 0, "Icon Style:" }; resource 'dctb' (rPrefsDialog, preload) { { }, { } }; /* New Preferences resources: Array of strings; layout determined on the fly First character determines type: ! Static text . Radio button / Checkbox $ Edit text? resource 'STR#' (rOpenPrefs, preload) { { "!Open new images on the:", ".Deepest screen", ".Largest screen", ".Main (menubar) screen", "/Color screens preferred", "!Use full screen windows for new images:", ".Always", ".Always for large images", ".Ask first for large images", ".Never, even for large images", "/Expand small images to maximum size", "/Allow only one open image at a time" } }; */ resource 'DITL' (rPrefsDialog, preload) { { { 40, 23, 58, 373 }, StaticText { disabled, "Open new images on the:" }, { 58, 43, 76, 353 }, RadioButton { enabled, "Deepest screen" }, { 76, 43, 94, 353 }, RadioButton { enabled, "Largest screen" }, { 94, 43, 112, 353 }, RadioButton { enabled, "Main (menubar) screen" }, { 122, 23, 140, 373 }, CheckBox { enabled, "Color screens preferred" }, { 150, 23, 168, 373 }, StaticText { disabled, "Use full screen windows for new images:" }, { 168, 43, 186, 353 }, RadioButton { enabled, "Always" }, { 186, 43, 204, 353 }, RadioButton { enabled, "Always for large images" }, { 204, 43, 222, 353 }, RadioButton { enabled, "Ask first for large images" }, { 222, 43, 240, 353 }, RadioButton { enabled, "Never, even for large images" }, { 250, 23, 268, 373 }, CheckBox { enabled, "Expand small images to maximum size" }, { 268, 23, 286, 373 }, CheckBox { enabled, "Allow only one open image at a time" }, { 40, 23, 58, 373 }, StaticText { disabled, "Display quality (screens with 256 or more colors):" }, { 58, 43, 76, 353 }, RadioButton { enabled, "Very high" }, { 76, 43, 94, 353 }, RadioButton { enabled, "High" }, { 94, 43, 112, 353 }, RadioButton { enabled, "Normal" }, { 122, 23, 140, 373 }, CheckBox { enabled, "Never do slow background updates" }, { 150, 23, 168, 373 }, StaticText { disabled, "Automatically reduce images to 16 or 256 colors:" }, { 168, 43, 186, 353 }, RadioButton { enabled, "Always, if appropriate" }, { 186, 43, 204, 353 }, RadioButton { enabled, "Only if no image colors are found" }, { 204, 43, 222, 353 }, RadioButton { enabled, "Never" }, { 232, 23, 250, 373 }, CheckBox { enabled, "Dither reduced color images " }, { 250, 23, 268, 373 }, CheckBox { enabled, "Use image colors, if available" }, { 268, 23, 286, 373 }, CheckBox { enabled, "Restore colors when closing last image" }, { 40, 23, 58, 373 }, StaticText { disabled, "Offscreen bitmaps are:" }, { 58, 43, 76, 353 }, RadioButton { enabled, "Always required" }, { 76, 43, 94, 353 }, RadioButton { enabled, "Optional, if memory is available" }, { 94, 43, 112, 353 }, RadioButton { enabled, "Never created" }, { 122, 23, 140, 373 }, CheckBox { enabled, "Maintain bitmaps at imageÕs original size" }, { 140, 23, 158, 373 }, CheckBox { enabled, "DonÕt use bitmaps for uncompressed images" }, { 40, 23, 58, 373 }, CheckBox { enabled, "Automatically fix incorrect file types" }, { 58, 23, 76, 373 }, CheckBox { enabled, "Change fixed filesÕ creator to JPEGView" }, { 86, 23, 104, 373 }, StaticText { disabled, "Save reduced color information:" }, { 104, 43, 122, 353 }, RadioButton { enabled, "Always" }, { 122, 43, 140, 353 }, RadioButton { enabled, "Only if no image colors were found" }, { 140, 43, 158, 353 }, RadioButton { enabled, "Never" }, { 168, 23, 186, 373 }, CheckBox { enabled, "Save JPEGs in PICT format by default" }, { 186, 23, 204, 373 }, CheckBox { enabled, "Include previews with saved images" }, { 204, 23, 222, 373 }, CheckBox { enabled, "Compress JFIF preview images" }, { 222, 23, 240, 373 }, CheckBox { enabled, "Create custom icons when saving images" }, { 248, 23, 288, 373 }, Control { enabled, rIconPopupControl }, { 40, 23, 58, 373 }, StaticText { disabled, "On startup:" }, { 58, 43, 76, 353 }, RadioButton { enabled, "Repeat the last slide show" }, { 76, 43, 94, 353 }, RadioButton { enabled, "Present the Slide Show Options dialog" }, { 94, 43, 112, 353 }, RadioButton { enabled, "Present the Open dialog" }, { 112, 43, 130, 353 }, RadioButton { enabled, "Do nothing" }, { 140, 23, 158, 373 }, CheckBox { enabled, "Automatic comments window control" }, { 168, 23, 186, 373 }, StaticText { disabled, "Time given to other applications:" }, { 186, 43, 204, 353 }, RadioButton { enabled, "Maximal" }, { 204, 43, 222, 353 }, RadioButton { enabled, "Reasonable" }, { 222, 43, 240, 353 }, RadioButton { enabled, "Minimal" }, { 250, 23, 268, 373 }, CheckBox { enabled, "Use QuickTime to decompress JPEGs" }, { 13, 30, 33, 203 }, Control { enabled, rPrefsMenuControl }, { 23, 13, 296, 383 }, UserItem { disabled }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rPrefsDialog } } } }; /***********************************************************************/ /************************ *************************/ /************************ About Help Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rAboutHelpDialog, preload) { { 0, 0, 143, 264 }, noGrowDocProc, invisible, goAway, kAboutHelpDialogID, rAboutHelpDialog, "About JPEGView Help", noAutoCenter }; resource 'DITL' (rAboutHelpDialog, preload) { { { 13, 10, 130, 254 }, Picture { disabled, rAboutHelpPict }, } }; /***********************************************************************/ /************************ *************************/ /************************ Progress Dialog *************************/ /************************ *************************/ /***********************************************************************/ resource 'DLOG' (rProgressDialog, preload) { { 0, 0, 75, 300 }, movableDBoxProc, invisible, noGoAway, kProgressDialogID, rProgressDialog, "JPEGView Progress", noAutoCenter }; resource 'dctb' (rProgressDialog, preload) { { }, { } //#ifndef oldTemp // ,{ } //#endif }; resource 'DITL' (rProgressDialog, preload) { { { 7, 10, 23, 290 }, StaticText { disabled, "^0:" }, { 50, 10, 60, 205 }, UserItem { disabled }, { 45, 215, 65, 290 }, Button { enabled, "Cancel" }, { 25, 10, 41, 290 }, StaticText { disabled, "Ò^3ÓÉ" }, } }; /***********************************************************************/ /*********************** *************************/ /*********************** Modal Progress Dialog *************************/ /*********************** *************************/ /***********************************************************************/ resource 'DLOG' (rModalProgressDialog, preload) { { 0, 0, 75, 300 }, dBoxProc, invisible, noGoAway, kProgressDialogID, rModalProgressDialog, "JPEGView Progress", noAutoCenter }; resource 'dctb' (rModalProgressDialog, preload) { { }, { } //#ifndef oldTemp // ,{ } //#endif }; resource 'DITL' (rModalProgressDialog, preload) { { { 7, 10, 23, 290 }, StaticText { disabled, "^0:" }, { 50, 10, 60, 205 }, UserItem { disabled }, { 45, 215, 65, 290 }, Button { enabled, "Cancel" }, { 25, 10, 41, 290 }, StaticText { disabled, "Ò^3ÓÉ" }, } }; /***********************************************************************/ /************************ *************************/ /************************ Minor Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rMinorAlert, preload) { { 0, 0, 105, 310 }, rMinorAlert, beepStages, noAutoCenter }; resource 'DITL' (rMinorAlert, preload) { { { 75, 225, 95, 300 }, Button { enabled, "OK" }, { 8, 75, 65, 300 }, StaticText { disabled, "Error: ^0" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rMinorAlert } } } }; /***********************************************************************/ /************************ *************************/ /************************ Fatal Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rFatalAlert, preload) { { 0, 0, 105, 310 }, rFatalAlert, beepStages, noAutoCenter }; resource 'DITL' (rFatalAlert, preload) { { { 75, 225, 95, 300 }, Button { enabled, "Finder" }, { 8, 75, 65, 300 }, StaticText { disabled, "Fatal Error: ^0" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rFatalAlert } } } }; /***********************************************************************/ /************************ *************************/ /************************ Unknown Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rUnknownAlert, preload) { { 0, 0, 105, 310 }, rUnknownAlert, beepStages, noAutoCenter }; resource 'DITL' (rUnknownAlert, preload) { { { 75, 225, 95, 300 }, Button { enabled, "OK" }, { 8, 75, 65, 300 }, StaticText { disabled, "Hey! This wasnÕt supposed to happen! Unknown " "Error #^0. Proceed with caution." }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rFatalAlert } } } }; /***********************************************************************/ /************************ *************************/ /************************ End Slides Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rEndSlidesAlert, preload) { { 0, 0, 105, 310 }, rEndSlidesAlert, beepStages, noAutoCenter }; resource 'DITL' (rEndSlidesAlert, preload) { { { 75, 225, 95, 300 }, Button { enabled, "OK" }, { 8, 75, 65, 300 }, StaticText { disabled, "The slide show has ended." }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rEndSlidesAlert } } } }; /***********************************************************************/ /************************ *************************/ /************************ Slide Memory Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rSlideMemAlert, preload) { { 0, 0, 115, 310 }, rSlideMemAlert, beepStages, noAutoCenter }; resource 'DITL' (rSlideMemAlert, preload) { { { 85, 225, 105, 300 }, Button { enabled, "OK" }, { 8, 75, 75, 300 }, StaticText { disabled, "There is not enough memory to display all the selected " "images; proceeding from here will result in an incomplete " "slide show." }, { 85, 140, 105, 215 }, Button { enabled, "Cancel" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rSlideMemAlert } } } }; /***********************************************************************/ /************************ *************************/ /************************ Too Big Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rTooBigAlert, preload) { { 0, 0, 115, 310 }, rTooBigAlert, silentStages, noAutoCenter }; resource 'DITL' (rTooBigAlert, preload) { { { 85, 225, 105, 300 }, Button { enabled, "Full" }, { 8, 10, 75, 300 }, StaticText { disabled, "The image Ò^1Ó is too large to fit in an onscreen window without " "scaling. Do you want to open it in a full screen window?" }, { 85, 140, 105, 215 }, Button { enabled, "Normal" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rTooBigAlert } } } }; /***********************************************************************/ /************************ *************************/ /************************ Bad JPEG Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rBadJPEGAlert, preload) { { 0, 0, 135, 310 }, rBadJPEGAlert, silentStages, noAutoCenter }; resource 'DITL' (rBadJPEGAlert, preload) { { { 105, 225, 125, 300 }, Button { enabled, "OK" }, { 8, 75, 95, 300 }, StaticText { disabled, "The JPEG image Ò^1Ó appears to be corrupt, and may cause QuickTime to " "crash your system. Do you still wish to try viewing it?" }, { 105, 140, 125, 215 }, Button { enabled, "Cancel" }, { 0, 0, 0, 0 }, HelpItem { disabled, HMScanhdlg { rTooBigAlert } } } }; /***********************************************************************/ /************************ *************************/ /************************ Needs 68020 Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rNeeds68020Alert, preload) { { 125, 101, 230, 411 }, rNeeds68020Alert, beepStages, noAutoCenter }; resource 'DITL' (rNeeds68020Alert, preload) { { { 75, 225, 95, 300 }, Button { enabled, "Finder" }, { 8, 75, 65, 300 }, StaticText { disabled, "Fatal Error: JPEGView requires a 68020 or " "better processor to run!" }, } }; /***********************************************************************/ /************************ *************************/ /************************ Needs Sys 7 Alert *************************/ /************************ *************************/ /***********************************************************************/ resource 'ALRT' (rNeedsSystem7Alert, preload) { { 125, 101, 230, 411 }, rNeedsSystem7Alert, beepStages, noAutoCenter }; resource 'DITL' (rNeedsSystem7Alert, preload) { { { 75, 225, 95, 300 }, Button { enabled, "Finder" }, { 8, 75, 65, 300 }, StaticText { disabled, "Fatal Error: JPEGView requires System 7 or " "later to run!" }, } }; \ No newline at end of file diff --git a/Resources/GeneralHelpResources.r b/Resources/GeneralHelpResources.r new file mode 100644 index 0000000..93d539c --- /dev/null +++ b/Resources/GeneralHelpResources.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ /* * JPEGView resource definition file * */ #define SystemSevenOrLater 1 #include "SysTypes.r" #include "Types.r" #include "BalloonTypes.r" #include "JPEGView.r.h" #define generalHelpOffset 3000 /***********************************************************************/ /******************* **********************/ /******************* Statistics Window **********************/ /******************* **********************/ /***********************************************************************/ resource 'hrct' (rStatWindow, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, { HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 1 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 2 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 3 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 4 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 5 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 6 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 7 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 8 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 9 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 10 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 11 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 12 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 13 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 14 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 15 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rStatWindow + generalHelpOffset, 16 } } }; resource 'STR#' (rStatWindow + generalHelpOffset, purgeable) { { "Statistics floating window\n\n" "This floating window gives a brief list of information about the " "active image. Click the zoom box on the right side of the title bar " "for more detailed information.", "JPEGView credits\n\n" "Just like in the movies! Sit back, eat your popcorn, and find out " "who (and what) made it all happen.", "Statistics floating window\n\n" "This floating window lists information about the " "active image. Click the zoom box on the right side of the title bar " "to shrink the information to a one-line summary.", "This is the name of the file that the active image was read from.", "This is size of the active image, given as horizontal pixels x vertical " "pixels. If the image has been cropped, the original size of the image " "is displayed as well, in the same format.", "This is number of colors contained in the active image.", "This is the ÒstatusÓ of the active image. Images can be Aborted " "(interrupted while drawing), Banded (in several pieces), Cropped " "(part of a larger image), or Corrupt (bad data).", "This is the compression method used on the active image. QuickTime-" "compressed PICT files and some JPEG images will also display an " "indication of the quality used in compression.", "This is the data format that was read from the active imageÕs original file.", "This is the length of the image data, in kilobytes (K).", "This is the size of the window used to display the active image. If this " "size is not equal to the original imageÕs size, the amount of scaling " "is given as a percent (or as horizontal %/vertical %).", "This is the set of colors currently selected to use for displaying the " "active image. If dithering has been disabled, it is indicated here as " "well.", "This is the quality level used when drawing the active image.", "This is the amount of time, in seconds, needed to decompress and display " "the image from the original data.", "This is the size, in kilobytes (K), of the offscreen bitmap used to do " "fast window updating.", "This is the amount of free memory remaining, in kilobytes (K)." } }; /***********************************************************************/ /******************* **********************/ /******************* Comments window **********************/ /******************* **********************/ /***********************************************************************/ resource 'hrct' (rCommentsWindow, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, { HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rCommentsWindow + generalHelpOffset, 1 } } }; resource 'STR#' (rCommentsWindow + generalHelpOffset, purgeable) { { "Comments floating window\n\n" "This window displays any text comments that were found included with " "the active image." } }; /***********************************************************************/ /******************* **********************/ /******************* Colors window **********************/ /******************* **********************/ /***********************************************************************/ resource 'hrct' (rColorsWindow, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, { HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rColorsWindow + generalHelpOffset, 1 } } }; resource 'STR#' (rColorsWindow + generalHelpOffset, purgeable) { { "Colors floating window\n\n" "This window displays a sampling of the colors that this screen is " "currently set up to display." } }; /***********************************************************************/ /******************* **********************/ /******************* Image windows **********************/ /******************* **********************/ /***********************************************************************/ resource 'hrct' (rImageWindow, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, { HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rImageWindow + generalHelpOffset, 1 } } }; resource 'STR#' (rImageWindow + generalHelpOffset, purgeable) { { "This is a JPEGView image window.\n\n" "Hint: To change the size of the image, move " "to the bottom-right corner of the window, then click and drag when the " "cursor changes. Hold down the shift key for full resizing freedom." } }; /***********************************************************************/ /************************ *************************/ /************************ Help Window *************************/ /************************ *************************/ /***********************************************************************/ resource 'hrct' (rHelpWindow, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, { HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rHelpWindow + generalHelpOffset, 1 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rHelpWindow + generalHelpOffset, 2 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rHelpWindow + generalHelpOffset, 3 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rHelpWindow + generalHelpOffset, 4 } } }; resource 'STR#' (rHelpWindow + generalHelpOffset, purgeable) { { "Size box\n\n" "To change the height and width of the window, drag the size box.", "Scroll bar\n\n" "To scroll a little at a time, press one of the scroll arrows. " "To scroll by the windowful, click in the gray bar. " "To scroll to another part of the window, drag the scroll box.", "Use this pop-up menu to select a different help topic to display.", "This is the help information you requested. Use the scroll bar to the " "right to view the rest of the text. Use the pop-up menu above to " "choose a new topic." } }; /***********************************************************************/ /************************ *************************/ /************************Slide Controls Window *************************/ /************************ *************************/ /***********************************************************************/ resource 'hrct' (rSlideControlsWindow, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, { HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 1 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 2 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 3 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 4 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 5 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 6 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 7 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 8 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 9 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 10 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, 0, 0 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, 0, 0 }, HMStringResItem { { 0, 0 }, { 0, 0, 0, 0 }, rSlideControlsWindow + generalHelpOffset, 11 } } }; resource 'STR#' (rSlideControlsWindow + generalHelpOffset, purgeable) { { "This status line describes what JPEGView is currently busy doing " "in order to prepare the next slide for display.", "Reverse button\n\n" "To manually return to the previous slide, click here. Note that there may " "be a delay as the slide is loaded and prepared for viewing.", "Stop button\n\n" "To end the slide show, click here.", "Pause button\n\n" "To pause the slide show and display the menu bar, click here. Hold " "down the option key and click here to hide the slide show.", "Forward button\n\n" "To manually advance to the next slide, click here. Note that there may " "be a delay as the slide is loaded and prepared for viewing.", "Reverse button\n\n" "Manually returns to the previous slide. Depressed because " "JPEGView is waiting to process your request.", "Stop button\n\n" "Ends the slide show. Depressed because JPEGView is waiting " "to process your request.", "Pause button\n\n" "The slide show is currently paused. To resume the slide show " "where you left off, click here.", "Forward button\n\n" "Manually advances to the next slide. Depressed because " "JPEGView is waiting to process your request.", "Reverse button\n\n" "Manually returns to the previous slide. Not " "available because JPEGView cannot back up from the current " "slide.", "Forward button\n\n" "Manually advances to the next slide. Not " "available because JPEGView cannot advance from the current " "slide." } }; \ No newline at end of file diff --git a/Resources/GeneralResources.r b/Resources/GeneralResources.r new file mode 100644 index 0000000..aa0c423 --- /dev/null +++ b/Resources/GeneralResources.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ /* * JPEGView resource definition file * */ //==================================================== // NOTE: We needed to change two things for 3.2.1: // Explicit +1 in vers resources, and a ".1" in the // version strings in the STR# resources //==================================================== #define SystemSevenOrLater 1 #include "SysTypes.r" #include "Types.r" #include "BalloonTypes.r" #include "JPEGView.r.h" #define generalHelpOffset 3000 /***********************************************************************/ /************************ *************************/ /************************ Version Resource *************************/ /************************ *************************/ /***********************************************************************/ resource 'vers' (1) { (kVersion >> 8), (kVersion & 0xff), final, 0, verUS, "3.3fc1", "3.3fc1 ©1992Ð94, Aaron Giles\n" "All Rights Reserved" }; resource 'vers' (2) { (kVersion >> 8), (kVersion & 0xff), final, 0, verUS, "3.3fc1", #ifdef PPC "for PowerPC Macintoshes" #else #ifdef FAT "for 680x0 and PowerPC Macintoshes" #else "for 680x0 Macintoshes" #endif #endif }; /***********************************************************************/ /************************ *************************/ /************************ Size Resource *************************/ /************************ *************************/ /***********************************************************************/ resource 'SIZE' (0) { reserved, acceptSuspendResumeEvents, reserved, canBackground, doesActivateOnFGSwitch, backgroundAndForeground, dontGetFrontClicks, ignoreAppDiedEvents, is32BitCompatible, isHighLevelEventAware, localAndRemoteHLEvents, notStationeryAware, useTextEditServices, reserved, reserved, reserved, 1100 * 1024, 800 * 1024 }; resource 'SIZE' (-1) { reserved, acceptSuspendResumeEvents, reserved, canBackground, doesActivateOnFGSwitch, backgroundAndForeground, getFrontClicks, ignoreAppDiedEvents, is32BitCompatible, isHighLevelEventAware, localAndRemoteHLEvents, notStationeryAware, useTextEditServices, reserved, reserved, reserved, 800 * 1024, 800 * 1024 }; /***********************************************************************/ /************************ *************************/ /************************ FREF / BNDL / JVWR *************************/ /************************ *************************/ /***********************************************************************/ resource 'FREF' (rAPPLType) { kAPPLType, rAPPLID, "" }; resource 'FREF' (rPICTType) { kPICTType, rPICTID, "" }; resource 'FREF' (rJFIFType) { kJFIFType, rJFIFID, "" }; resource 'FREF' (rJPEGType) { kJPEGType, rJPEGID, "" }; resource 'FREF' (rHelpType) { kHelpType, rHelpID, "" }; resource 'FREF' (rGIFType) { kGIFType, rGIFID, "" }; resource 'FREF' (rAllTypes) { kAllTypes, rAllID, "" }; resource 'FREF' (rTIFFType) { kTIFFType, rTIFFID, "" }; resource 'FREF' (rBMPType) { kBMPType, rBMPID, "" }; resource 'FREF' (rSCRNType) { kSCRNType, rSCRNID, "" }; resource 'FREF' (rPNTGType) { kPNTGType, rPNTGID, "" }; resource 'BNDL' (rBNDLRsrc) { kCreator, rJVWRRsrc, { 'FREF', { rAPPLID, rAPPLType, rPICTID, rPICTType, rJFIFID, rJFIFType, rJPEGID, rJPEGType, rHelpID, rHelpType, rGIFID, rGIFType, rAllID, rAllTypes, rTIFFID, rTIFFType, rBMPID, rBMPType, rSCRNID, rSCRNType, rPNTGID, rPNTGType }, 'ICN#', { rAPPLID, rAPPLIcon, rPICTID, rPICTIcon, rJFIFID, rJPEGIcon, rJPEGID, rJPEGIcon, rHelpID, rHelpIcon, rGIFID, rGIFIcon, rAllID, rOtherIcon, rTIFFID, rTIFFIcon, rBMPID, rBMPIcon, rSCRNID, rSCRNIcon, rPNTGID, rPNTGIcon } } }; type kCreator as 'STR '; resource kCreator (rJVWRRsrc) { "JPEGView Version 3.2" }; /***********************************************************************/ /************************ *************************/ /************************ Finder Help *************************/ /************************ *************************/ /***********************************************************************/ resource 'hfdr' (-5696, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, { HMStringItem { "JPEGView is a nifty utility that can quickly view JPEG, GIF, TIFF, " "PICT, MacPaint, and Startup Screen files. It even comes with " "a slide show and extensive on-line help!" } } }; /***********************************************************************/ /******************* **********************/ /******************* Statistics Window **********************/ /******************* **********************/ /***********************************************************************/ resource 'WIND' (rStatWindow, preload) { { 0, 0, 100, 100 }, windoidZoomProc, invisible, goAway, kStatWindowID, "Statistics", noAutoCenter }; /***********************************************************************/ /******************* **********************/ /******************* Comments window **********************/ /******************* **********************/ /***********************************************************************/ resource 'WIND' (rCommentsWindow, preload) { { 0, 0, 100, 100 }, windoidProc, invisible, goAway, kCommentsWindowID, "Comments", noAutoCenter }; /***********************************************************************/ /******************* **********************/ /******************* Colors window **********************/ /******************* **********************/ /***********************************************************************/ resource 'WIND' (rColorsWindow, preload) { { 0, 0, 49, 257 }, windoidProc, invisible, goAway, kColorsWindowID, "Colors", noAutoCenter }; resource 'wctb' (rColorsWindow, preload) { { }, { } }; /***********************************************************************/ /******************* **********************/ /******************* Image windows **********************/ /******************* **********************/ /***********************************************************************/ resource 'WIND' (rImageWindow, preload) { { 0, 0, 100, 100 }, zoomNoGrow, invisible, goAway, kImageWindowID, "", noAutoCenter }; resource 'wctb' (rImageWindow, preload) { { wContentColor, 0x0000, 0x0000, 0x0000, wFrameColor, 0x1111, 0x1111, 0x1111 }, { } }; resource 'WIND' (rFullImageWindow, preload) { { 0, 0, 100, 100 }, plainDBox, invisible, goAway, kImageWindowID, "", noAutoCenter }; resource 'wctb' (rFullImageWindow, preload) { { wContentColor, 0x0000, 0x0000, 0x0000, wFrameColor, 0x1111, 0x1111, 0x1111 }, { } }; resource 'WIND' (rAboutImageWindow, preload) { { 0, 0, 100, 100 }, noGrowDocProc, invisible, goAway, kImageWindowID, "", noAutoCenter }; resource 'wctb' (rAboutImageWindow, preload) { { wContentColor, 0x0000, 0x0000, 0x0000, wFrameColor, 0x1111, 0x1111, 0x1111 }, { } }; /***********************************************************************/ /************************ *************************/ /************************ Help Window *************************/ /************************ *************************/ /***********************************************************************/ resource 'WIND' (rHelpWindow, preload) { { 0, 0, 300, 480 }, zoomDocProc, invisible, goAway, kHelpWindowID, "JPEGView Help", noAutoCenter }; resource 'CNTL' (rHelpMenuControl, preload) { { 7, 0, 26, 375 }, popupTitleLeftJust, visible, 80, rHelpMenu, popupMenuCDEFProc, 0, "Help Topic:" }; resource 'CNTL' (rHelpScrollControl, preload) { { 22, 460, 279, 476 }, 0, visible, 0, 0, scrollBarProc, 0, "" }; /***********************************************************************/ /************************ *************************/ /************************Slide Controls Window *************************/ /************************ *************************/ /***********************************************************************/ resource 'WIND' (rSlideControlsWindow, preload) { { 0, 0, 29, 28 * 4 }, windoidProc, invisible, noGoAway, kSlideControlsWindowID, "Slide Show", noAutoCenter }; resource 'wctb' (rSlideControlsWindow, preload) { { }, { } }; /***********************************************************************/ /************************ *************************/ /************************ Error Messages *************************/ /************************ *************************/ /***********************************************************************/ resource 'STR#' (rFatalErrors, preload) { { "Not enough memory to start up!", "CouldnÕt load all the code resources!", "CouldnÕt load the string resources!", "CouldnÕt load the cursors!", "JPEGView requires System 7.0 or later to run!", "CouldnÕt find the system color tables!", "CouldnÕt load the application menus!", "CouldnÕt install the supported AppleEvents!", "Unable to identify the active screen devices!" } }; resource 'STR#' (rMinorErrors, preload) { { "Not enough memory to complete this operation.", "Your version of QuickTime has a strange version number; proceed with caution.", "CouldnÕt load the About dialog.", "CouldnÕt send the appropriate AppleEvent.", "CouldnÕt set up the Help window.", "CouldnÕt load the Preferences dialog.", "CouldnÕt write the Preferences file.", "No valid image files found.", "CouldnÕt load the Slide Show dialog.", "CouldnÕt create the preview image.", "No printer is selected. Please open the Chooser and select a printer.", "JPEGViewÕs help file ÒJPEGView HelpÓ could not be found in the JPEGView folder." } }; resource 'STR#' (rStringErrors, preload) { { "The image data for Ò^1Ó is corrupt.", "Ò^1Ó is not a valid image file.", "Unable to open the input file Ò^1Ó.", "Not enough memory to draw the image Ò^1Ó.", "Not enough memory to load the file Ò^1Ó.", "Unable to read the file Ò^1Ó.", "Unable to write the file Ò^1Ó.", "Unable to create the file Ò^1Ó.", "Not enough memory to convert Ò^1Ó into a PICT.", "Not enough memory to convert Ò^1Ó into JFIF format.", "Unable to open a window for Ò^1Ó.", "Not enough memory to create an offscreen bitmap for Ò^1Ó.", "Not enough memory to reduce Ò^1Ó.", "Unable to create a preview image for Ò^1Ó.", "Not enough memory to save the color reduction in Ò^1Ó.", "Unable to create custom icons for Ò^1Ó.", "Not enough memory to crop Ò^1Ó.", "Not enough memory to save Ò^1Ó.", "Ò^1Ó is an HSI JPEG file, in a proprietary format that JPEGView cannot read.", "Not enough memory to print the file Ò^1Ó.", "Unable to print the image Ò^1Ó.", "Not enough memory to copy the image Ò^1Ó.", "Ò^1Ó is not a Baseline or LZW-compressed TIFF image.", "The image Ò^1Ó could not be displayed because QuickTimeª is not installed.", "Corrupt JPEG data found (^1).", "The file Ò^1Ó contains BinHex-encoded data, which must be decoded before opening.", "The file Ò^1Ó contains uuencoded data, which must be decoded before opening." } }; resource 'STR#' (rGenericStringErrors, preload) { { "The image data is corrupt.", "This is not a valid image file.", "Unable to open the input file.", "Not enough memory to draw the image.", "Not enough memory to load the file.", "Unable to read the file.", "Unable to write the file.", "Unable to create the file.", "Not enough memory to convert the image into a PICT.", "Not enough memory to convert the image into JFIF format.", "Unable to open a window for this image.", "Not enough memory to create an offscreen bitmap for this image.", "Not enough memory to reduce this image.", "Unable to create a preview.", "Not enough memory to save the color reduction with this image.", "Unable to create custom icons for this image.", "Not enough memory to crop this image.", "Not enough memory to save this image.", "This image is an HSI JPEG file, in a proprietary format that JPEGView cannot read.", "Not enough memory to print this image.", "Unable to print this image.", "Not enough memory to copy this image.", "This image is not a Baseline or LZW-compressed TIFF.", "This image could not be displayed because QuickTimeª is not installed.", "Corrupt JPEG data found (^1).", "This file contains BinHex-encoded data, which must be decoded before opening.", "This file contains uuencoded data, which must be decoded before opening." } }; /***********************************************************************/ /************************ *************************/ /************************ General Strings *************************/ /************************ *************************/ /***********************************************************************/ resource 'STR#' (rStrings, preload) { { "File Name: ", "Image Size: ", "Image Colors: ", "Image Status: ", "Compression: ", "File Format: ", "Image Length: ", "Displayed Size: ", "Displayed Colors: ", "Display Quality: ", "Display Time: ", "Offscreen Bitmap: ", "Free Memory: ", "~1 x ~2", // Image size "~1 x ~2 (originally ~3 x ~4)", "~1", // Image colors "~1 grayscales", "Normal", // Image status "Aborted", "Banded", "Cropped", "Corrupt", "LZW/GIF", // Image compression "JPEG (Adobe)", "JPEG (QuickTime)", " (quality: ~1.~2)", "JPEG (est. IJG quality: ~1)", "JPEG", "Uncompressed", "PICT", // File format "JFIF", "GIF", "~1K", // Image length "~1K, or ~2% compression", "~1K, or ~2:1 compression", "~1 x ~2", // Displayed size "~1 x ~2 (scaled by ~3%)", "~1 x ~2 (scaled by ~3%/~4%)", "~1", // Displayed colors "~1, without dithering", "~1 system colors", "~1 grayscales", "~1 image colors", "~1 reduced colors", "~1 system colors, without dithering", "~1 grayscales, without dithering", "~1 image colors, without dithering", "~1 reduced colors, without dithering", "Very high", // Display quality "High", "Normal", "n/a", "~1.~2 seconds", // Display time "No bitmap", // Offscreen bitmap "~1K", "~1K, at imageÕs original size", "~1K", // Free memory "~1: ~2K ~3, ~4 x ~5 x ~6", // Summary lines "Thousands", "Millions", "JPEGView", "JPEGView Help", "JPEGView PICT", "JPEGView Preferences", "JVTmpFil", "Select", "Desktop", "DecompressingÉ ~1%", "DitheringÉ ~1%", "ScalingÉ ~1%", "Reducing to ^1 colors", "Creating preview image", "Creating custom icons", "Creating preview and icons", "Saving", " ", "Just a reminder...", " ", "JPEGView is postcardware", "Have you sent in your postcard yet?", " ", "It only takes a couple minutes!", "Aaron Giles", "182 E. 95th Street 11E", "New York, NY 10128 U.S.A.", " ", "I look forward to hearing from you!", "No comments found", "Restart", "Resume", "Show Statistics", "Hide Statistics", "Show Comments", "Hide Comments", "Show Colors", "Hide Colors", "Begin Slide Show", "Resume Slide Show", "", "About JPEGView", "version ~1.~2, running native on a PowerPC", "version ~1.~2", "Loading: ~1", "Reducing: ~1", "Drawing: ~1", "Ready", "Paused", "Delaying... ~1", "Rendering: ~1", "Scanning folder", "Printing", "Copying", "Preparing", "Modified CCITT RLE", "PackBits", "LZW", "4-bit RLE", "8-bit RLE", "LZW with prediction", "JPEGView Help" } }; resource 'STR#' (rFormatNames, preload) { { "PICT", "JFIF", "GIF", "TIFF", "BMP", "Startup Screen", "MacPaint", "PICT Resource" } }; \ No newline at end of file diff --git a/Resources/Help Text/01.Overview b/Resources/Help Text/01.Overview new file mode 100644 index 0000000..d1a46ce --- /dev/null +++ b/Resources/Help Text/01.Overview @@ -0,0 +1 @@ +JPEGView Version 3.3 Ñ May, 1994 written by Aaron Giles What is JPEGView? In simplest terms, JPEGView is a fast, powerful postcardware utility for the Macintosh designed to provide simple, high-quality viewing of PICT, JFIF, GIF, TIFF, BMP, MacPaint, and Startup Screen images. JPEGView is not an all-purpose format conversion utility; however, it does support a save function to allow QuickTime previews and custom color icons to be added to images of any format. It can also perform the very simple translation between JPEG-compressed PICT files and the standard JPEG interchange format JFIF. JPEGView is postcardware, so if you find yourself using JPEGView regularly, you should send me a postcard (and for the last time, email does not count as a postcard Ñ sorry!). Details, including my current address, are given in the chapter titled Contacting the Author, later in this document. Important: while I love hearing from JPEGView users through email, I would like to ask that you take the time and effort to send in a real paper and ink postcard. Not only are they more colorful, but they last a lot longer, and donÕt disappear when my hard drive crashes. WhatÕs new in JPEGView 3.3 JPEGView 3.3 has been designed to fix several problems that were found in the version 3.2 release, and to add a few more interesting bits to JPEGViewÕs functionality. Specifically, hereÕs an overview of whatÕs new, and in which chapter the associated changes are reflected: Improved JPEG support. JPEGView started its life as a QuickTime-dependent JPEG viewer, and has since evolved into something much more. Beginning with version 3.3, QuickTime is no longer even needed to view JPEG images, as JPEGView incorporates the Independent JPEG GroupÕs code for decoding JPEGs. The new code is much more robust than QuickTime, but significantly slower on 680x0 Macintoshes (and about the same speed as QuickTime on a Power Macintosh). Thus, you can trade off speed for robustness by choosing not to use QuickTime for JPEG images; this choice is controlled from the last panel in the Preferences window (Preferences Settings). Better icon creation. This latest version of JPEGView now supports four distinct icon styles, so you can create your icons in your favorite style; this choice is made in the ÒSavingÓ panel of the Preferences window. In addition, you can now select a smaller area of the image to be represented by the icon, thus ensuring that you can accurately distinguish your files from within the Finder. (Preferences Settings, Saving Images). Faster drawing. A new scaling algorithm has been incorporated into JPEGViewÕs High quality drawing, resulting in a 25-75% speed increase when using this drawing mode. Image quality under the new algorithm is slightly worse than in previous versions, so the default quality is now Very High, to ensure the best quality drawing. (Colors and Color Reduction). Drag and drop support. If you have the Macintosh Drag and Drop extension installed in your System Folder (or if you are running System 7.5 or later), JPEGView can now take advantage of it in several ways. First, you can drag a selection made in JPEGView outside of its original window and drop it into any other application which supports dropped pictures. This is similar to copying the selected portion of the image in JPEGView and pasting into another application, only much faster. You can also drag the text from JPEGViewÕs Statistics and Comments floating windows into another application. Finally, when using Finder 7.1.2 or later, you can drag a folder from the desktop into the Slide Show Options window to choose that folder for a slide show. (The How and Why of Floating Windows, Special Effects, Slide Show). More robust memory management. The tricks that JPEGView uses to reign in QuickTimeÕs use of memory on systems running with virtual memory or with ConnectixÕs RAMDoubler product have been improved. Previous versions of JPEGView would sometimes incorrectly report corrupt images or prevent certain system extensions from working. The memory management in JPEGView 3.3 should fix most if not all of these problems. Additional minor features. Cropped images of any format are now allowed to be saved from JPEGView, and their cropping rectangles will be remembered in the future (Saving Images). A redesigned Òmarching antsÓ animation technique allows selections to be seen much more clearly. PICTs saved at other than 72dpi are always opened to their full resolution. And a new version of the JPEGView JFIF Preview extension works more smoothly as a fat binary. If you have been using JPEGView 3.0 or later, you should have no trouble adjusting to the new features in 3.3. If you have used any versions of JPEGView prior to 3.0, it is highly recommended that you familiarize yourself with the operation of the new features by reviewing this updated documentation carefully. The most important new features are described in the Scripting JPEGView, Colors and Color Reduction, and Slide Show chapters. Postcards, registration, and licensing Once again, I am releasing JPEGView to individual users as postcardware, meaning that if you use it, even casually, you are asked to send me a real Òsnail-mailÓ postcard of some sort Ñ and no excuses! Even if you live next door to me, or have sent me an email message, please take the time to drop me a real pen and ink postcard anyway. I guarantee you that the dollar or so that you spend is one of the best software bargains youÕll find anywhere Ñ and IÕd really love to have tangible proof that youÕre using JPEGView! Any user of JPEGView 3.0 or later also has the option of becoming a fully registered user. Registered users who send in a one-time registration fee of US$20 receive a printed, bound copy of the full JPEGView documentation, along with an official JPEGView 3.3 release disk, containing the complete JPEGView 3.3 release plus a few of my favorite JPEG images. My current U.S. Mail address can be found in the chapter Contacting the Author, later on in this documentation. Overseas users who wish to avoid the hassle and fees of international money orders are asked to simply send the equivalent of US$20 in cash, plus about US$3 extra for postage (everything is sent airmail). Although this is not recommended by the post office, you can usually get away with it as long as you do well to mask the fact that there is cash enclosed, i.e., make sure it is wrapped in sufficiently opaque paper. Note that registration is optional; the only ÒpaymentÓ that is required for individual use of JPEGView is a postcard. Finally, a very simple unlimited site license is available for universities and companies that wish to make JPEGView 3.3 an officially supported product Ñ and it typically only costs you the low low price of a few individual registrations (US$50 to be exact)! Contact me via email (giles@med.cornell.edu) or U.S. Mail (in Contacting the Author) for full details, or just go ahead and send in the cash (most people seem to do it anyway!) Purchase orders are welcome. Organizations and individuals who are interested in distributing JPEGView with their products should contact me first before doing so. IÕm usually pretty flexible about licensing, especially for Ògood causesÓ, so if youÕre interested, please donÕt hesitate to get in touch with me about it! Legal mumbo jumbo The JPEGView application, documentation, and all associated items in the JPEGView package are copyright © 1992-94, Aaron Giles. All Rights Reserved. The only exceptions to this are the Infinity Windoid WDEF, which is copyrighted by Troy Gaul; the Mercutio MDEF, which is copyrighted by Ramon Felciano; and the Independent JPEG GroupÕs JPEG decompression code, which is copyrighted by Tom Lane. A license to the use of this software is freely granted. This software may be freely copied on an individual basis, provided that the original, unmodified package, including all supplementary documentation, all support code, and all examples, is provided intact. The distribution of this software in conjunction with any other product is prohibited, without the prior consent of the author, Aaron Giles. This software is provided Òas isÓ without warranty of any kind. The entire risk as to the quality and performance of this software is with the user. The author, Aaron Giles, shall have no liability or responsibility to the user or any other person or entity with respect to any claim, loss, liability, or damage caused or alleged to be caused directly or indirectly by this software. This disclaimer includes but is not limited to any interruption of services, loss of business or anticipatory profits or any incidental, consequential and/or other damages of any kind resulting from the use or operation of this software. \ No newline at end of file diff --git a/Resources/Help Text/02.Viewing Images b/Resources/Help Text/02.Viewing Images new file mode 100644 index 0000000..441d2bf --- /dev/null +++ b/Resources/Help Text/02.Viewing Images @@ -0,0 +1 @@ +Viewing Images At its heart, JPEGView is a simple image viewer, designed to provide a high-quality screen image in as little time and with as little fuss as possible. Opening images for viewing is as simple as with most any other Macintosh application: select the Open menu item from the File menu (or type O), choose your image file in the dialog box, and let JPEGView do the rest. Closing an image just requires clicking in the close box or choosing Close from the File menu (W). For its basic operations, JPEGView works just as youÕd expect. Beyond these simple operations, however, JPEGView supports a rich variety of features which allow even easier navigation through your image files. This chapter describes how these features work in greater detail, under JPEGViewÕs normal, or ÒdefaultÓ settings. Like many Macintosh applications, the exact way JPEGView works can be changed by altering the settings presented in the Preferences dialog box, available under the Preferences item in the File menu. For a precise description of how these changes affect JPEGViewÕs operation, see the chapter on Preferences Settings. Opening images, with and without previews When you choose Open from the File menu, what you get back is not the usual dialog youÕre used to. Fortunately, all the basic features are still there, allowing you to select a file to open in the usual manner. But JPEGView offers you two important additions: the ÒShow PreviewÓ checkbox and the ÒScan for Image FilesÓ button. If youÕve used QuickTime applications before, you have undoubtedly encountered the ÒShow PreviewÓ option in your Open dialogs. The principle is simple: in certain types of files which QuickTime understands, a preview (a.k.a. thumbnail) image can be stored along with the original image data. This preview image is simply a small (usually about 80 pixels square) representation of the full image contained in the file. This allows you to see in advance what you will get once you open the image file, before having to actually open it and wait through the full decompression of the image inside. To turn the previewing feature on, simply check the ÒShow PreviewÓ box beneath the file list. In response, the Open dialog will expand horizontally to include a new Preview area, where these small preview images will be displayed. Once you have done this, you can view the preview stored in an image file with just a single click on the name of the file in the list. If the file you select contains a preview image, it will be read from disk and displayed in the Preview area after a second or so. If the ÒShow PreviewÓ box is checked and you highlight an image file which has no preview, the ÒCreateÓ button beneath the Preview area will become active, allowing you to automatically create a preview for that image inside the Open dialog. Occasionally when you select an image file, the ÒCreateÓ button will change to an ÒUpdateÓ button and become active; this simply means that the preview stored with the image isnÕt up-to-date. To remedy the situation, click on the button to create an updated preview. Finally, if you do not wish to see previews anymore Ñ they can be slow at times, especially from slower disks like floppies and CD-ROMs Ñ you can always uncheck the ÒShow PreviewÓ box, which will return the Open dialog to its normal, skinnier size. QuickTime handles the job of remembering whether you checked this box the last time you used it, so that the next time you run a QuickTime application (including JPEGView), this option will be left as you last set it. The JPEGView JFIF Preview extension Preview images are very nice, but unfortunately not all previews are created equally. JPEGView, together with QuickTime, provides support for viewing preview images for almost all image types automatically, without any special mechanisms. However, there is one limitation, and one exception to this feature. The limitation is that although JPEGView can create previews when saving any of its supported image formats, QuickTime only knows how to create previews for PICT images; this means that the ÒCreateÓ button under the Preview area will always be dimmed when a non-PICT image is selected. The exception to free preview images is the JFIF file format, which has a preview format all its own. In order to display these special previews, you will need to install the JPEGView JFIF Preview extension, which ships with this release of JPEGView. To install the JPEGView JFIF Preview extension on your Macintosh, simply drag its icon on top of your System Folder icon, or manually place it in the Extensions folder within your System Folder. You will need to restart your computer to get QuickTime to notice the new extension, after which you should be able to see JFIF previews effortlessly, even from within applications other than JPEGView. It is important to realize two quirks about the way this extension works. First, you will notice that the ÒCreateÓ button under the preview is always dimmed; this is simply because the JPEGView JFIF Preview extension was not designed to allow you to create previews from within the open dialog. To create JFIF previews, you need to open the image and save it back again with the preview option checked in the Save dialog. This technique works equally well with other non-PICT images; see Saving Images for a full description of this procedure. The second quirk relating to the JPEGView JFIF Preview extension is that it will not display an icon at the bottom of your screen during startup. However, donÕt worry Ñ as long as itÕs in your Extensions folder, you can be fairly certain that it has, in fact, loaded successfully. How to see images that donÕt appear in the file list Sometimes you may receive a file that JPEGView doesnÕt immediately recognize as a valid image file. This is especially true if you have copied an image from a BBS or from another type of machine. In order to draw up the list of files as quickly as possible, JPEGView initially checks only the FinderÕs file type information. Although this works quickly, it is possible (and sometimes inevitable) that the FinderÕs information about a file is incorrect. For example, when you double click on such an image, the Finder doesnÕt know what to do with it, or which application it should use to open the file with. So how do you get JPEGView to recognize these other files? This is where the ÒScan For Image FilesÓ button comes into play. Clicking on this button does two things: first, it checks all the files in the folder you are currently viewing for valid images. In order to make sure the Finder isnÕt lying, JPEGView actually opens each file and peeks inside at the contents. This works well, but be forewarned: if there are a lot of files, it can take some time! After it has finished checking all the files, JPEGView then goes through the list and fixes the FinderÕs information about these files. This means that in the future, the files that were found will appear in the Open dialog without any further intervention on your part. Plus, when you double click on these ÒfixedÓ files in the Finder, JPEGView will automatically load and open them for you. (If you have the folder visible on the desktop, you will see the icons for these files change to JPEGView icons after several seconds.) Unfortunately, certain graphics formats do not lend themselves well to automatic identification in this manner. Specifically, it is impossible to guarantee successful identification of MacPaint and Startup Screen files, apart from what the Finder says about them. For this reason, JPEGView requires that the FinderÕs information properly identify such files; incorrectly-typed files in these formats will give you an error if you attempt to open them. If you think that you might have a MacPaint or Startup Screen image with the wrong Finder file type, drag and drop its document icon onto the MacPaint AutoTyper or the Startup Screen AutoTyper application as appropriate. This will force the Finder information to properly identify the file, and may allow JPEGView to open it successfully. For more information about the AutoTypers, see the chapter on File Formats and File Types. Under certain circumstances, it is possible that the FinderÕs file type information cannot be changed. For example, if your incorrectly identified files are all on CD-ROM, there is no way to modify the information contained on the disc. To allow you to view such files, JPEGView supports an Import option, also available under the File menu (or by holding down the Shift key as you type O). This will give you a dialog identical to the Open dialog, only showing every file available, regardless of what the Finder has to say about it. Of course, JPEGView can still only open image files it knows about, but at least importing them means that they are all visible to you. What happens to the images when theyÕre opened Once youÕve chosen an image file in the Open dialog, JPEGView loads the file into memory and immediately attempts to verify that the file does in fact represent a valid image (remember that the Finder isnÕt always correct!) If the image passes this test, but its Finder information was incorrect, JPEGView will quietly fix this for you, to help keep everything in order. At this point, JPEGView also checks the size of the image you opened, comparing it to the size of your preferred monitor. If the image is too large to fit vertically on your screen, JPEGView will ask you if you wish to open the image in a full screen window. The advantage of full screen windows is that they have no title bar and hide the menu bar, giving you a little extra height in which to view the image. The Special Effects chapter describes how JPEGViewÕs full screen windows work more comprehensively. If the image you have opened is a high-color image (with thousands or millions of colors) and your screen is only capable of displaying 256 or 16 colors, JPEGView will then perform two-pass color reduction on the image to find the best set of colors for display. Because this process requires JPEGView to decompress the image, a progress window is displayed to let you know how far along JPEGView is. For more information on exactly what two-pass color reduction is and how it helps image quality, see the chapter on Colors and Color Reduction. Once everything is ready, a new window is opened on your desktop, and the image is decompressed. During the decompression process, the bottom right-hand corner of the imageÕs window will display a progress message, keeping you informed of how far along JPEGView is in decompressing the image data. Additionally, JPEGView indicates when it is performing a scaling or dithering operation by changing the progress message from ÒDecompressingÉÓ to read ÒScalingÉÓ or ÒDitheringÉÓ as appropriate. An important distinction between JPEGView and nearly every other image viewer available is the fact that JPEGView automatically shrinks large images so that they fit on your screen without any distortion. This is important not only because it allows you to always see the full image at one glance but also because you can easily select the area of interest when you do decide to zoom in and look at the details. It also means that you donÕt lose the extra area taken up by scroll bars, which is an important consideration for those with monitors smaller than 14Ó. The amount of time it takes to decompress a given image can vary widely, from under a second for a small uncompressed image to over three minutes for a huge JPEG-compressed image. JPEGView has been designed to give you nearly optimal speed for all compression methods. If the wait becomes too tedious, however, you always have the option to abort the drawing procedure by pressing either the Esc key on your keyboard, or by typing a period while holding down the  key. When you abort the drawing in this manner, JPEGView will fill in the remaining area with a pattern of XÕs, to let you know why it wasnÕt drawn. Fast and slow window updating Memory requirements for most image viewers are stiff, usually on the order of several megabytes for even reasonably sized JPEG files. This is because they require you to give them enough memory to decompress the whole image at once and store it offscreen for future use. While this may be simple and fast for scrolling around, if you try opening more than a couple of decent sized images you may be wondering why 20 megabytes of RAM doesnÕt seem like so much anymore. Once again, JPEGView takes a different approach. Internally, the workings of JPEGViewÕs memory management are a little complicated, but on the surface all you see is that some windows will redraw themselves immediately, while others need to have their images decompressed before display. This is known as fast updating and slow updating, respectively. HereÕs how it all works: When JPEGView first loads an image, it attempts to create an offscreen copy (called an offscreen bitmap) of what you see on the screen. It is important to realize that this offscreen bitmap need only be the size of the image you see on the screen, and not the size of the original image. This means that the amount of memory needed for the bitmap is only dependent on how large your screen is, and not on how large the original image was, which is precisely what most other image viewers require of you. If it turns out that there isnÕt enough memory available to make an offscreen bitmap for an image, itÕs all right; JPEGView can do without it. But if there is enough memory, this offscreen bitmap allows JPEGView to redraw obscured portions of that imageÕs window instantly. This is known as fast updating and can only be achieved if there is an offscreen copy of what you see on the screen available in memory. Notice that JPEGView does not require this offscreen bitmap. This is important, because when JPEGView realizes that it needs more memory, it will cheerfully get rid of enough of these offscreen bitmaps to make room for other, more important things. If you later close other images and free up more memory, JPEGView will quietly re-create these offscreen bitmaps; until then, such images are resigned to using slow updating, which means they have to be decompressed to be displayed again. When part of such a window needs to be updated, it is filled in with a sparse pattern of dots until JPEGView decides there is time to do the slow update. Of course, all this happens behind your back, so you never need to worry about it explicitly. What you actually see is this fast and slow updating. Fast updating always occurs immediately, whereas slow updating Ñ because at times it can be really slow Ñ is postponed until later, so that if youÕre in a rush and know what you want to do, you do not need to wait for it to happen. JPEGView determines this by waiting until you leave it alone for five seconds. Once you do this, it will begin doing all its slow updating one window at a time, from frontmost to backmost, waiting two and a half seconds between each to let you do something else. ItÕs a simple matter to see the difference between the two types of updates: fast updates immediately replace the obscured portion of the window, while slow updates paint the obscured area with a sparse pattern of dots until a full update is done. This lets you know that JPEGView is not ignoring the obscured area, only waiting a few seconds before updating it. Even if a slow update is in progress, you always have the option of stopping the decompression either by pressing the Esc key, or by typing a period while holding down the  key. Switching between JPEGViewÕs windows With JPEGViewÕs sparse memory requirements, it is possible to have many images open at once, even with only a megabyte of RAM available. In order to facilitate movement between these different windows, JPEGView has several useful windowing commands, as well as a slide show option Ñ described later in the Slide Show chapter Ñ which can cycle through all the images in memory. With the exception of the slide show, all of JPEGViewÕs window navigation commands can be found in the Windows menu. The most direct way to bring a given imageÕs window to the front (apart from clicking on the window itself) is by selecting it from the Windows menu. As you open images in JPEGView, their window titles are added to the bottom of the Windows menu for immediate access to every image currently in memory. Additionally, the first nine windows added to this list are assigned to the keyboard shortcuts 1 through 9, for even faster switching. You can quickly identify which window is currently active by looking for the entry in the list with a checkmark beside it. In addition to an entry for each open window, the Windows menu contains the Next Image (+) and Previous Image (Ð) items. With these two options you can cycle forward and backward through the list of open images. Finally, the topmost items in the Windows menu control the visibility of JPEGViewÕs three floating windows (sometimes called ÒwindoidsÓ). Floating windows are a special type of window whose behavior is independent of the other standard windows. See the chapter The How and Why of Floating Windows for a description of how they work and what information they convey. Putting things away Once youÕve mastered the art of window navigation, getting rid of the images seems a rather simple exercise. As you would expect, the close box on the window, the Close item in the File menu, and the W shortcut all close the active window, releasing any memory used by the associated image. Further, the convenient Close All Images option (Shift-W) quickly closes up all open image windows Ñ but not the Help window, the options dialogs, or any visible floating windows. This allows you to keep those windows open and available at all times, even letting you close all the image windows while they are active. You can also close several open windows at once by holding down the Option key as you click in the close box on one of the windows. If you option-click the close box of a floating window, JPEGView hides all floating windows; doing the same thing in a standard window closes all open standard windows (this time including the Help window and the options dialogs). Printing images In addition to all of this, JPEGView also supports a rather simple method for obtaining a hardcopy print of an image, assuming your printer properly handles printing of color images. If youÕre not sure whether your printer provides this support, simply try it out and see how the resulting image comes out. Either youÕll like it or you wonÕt; if you do, youÕre in luck. If not, cÕest la vie. Before printing an image, you will likely want to choose Page Setup from the File menu to set the paper direction (portrait or landscape) and other options. Once set, these options are saved and remembered until you change them again. From there, you can go ahead and choose Print (P) from the File menu; this will give you some more options, depending on which type of printer you are working with, and then let you start the ball rolling. JPEGView then puts up its familiar progress dialog, telling you how far along it is in printing the image, and proceeds to dump the image to the printer. Note that at this time, you have no control over what size the resulting image is printed at. JPEGView always scales the image to fit the current paper size, with half-inch margins on all four sides. Thus, printing an image from JPEGView will always give you a single-page printout. \ No newline at end of file diff --git a/Resources/Help Text/03.Floating Windows b/Resources/Help Text/03.Floating Windows new file mode 100644 index 0000000..f39f64c --- /dev/null +++ b/Resources/Help Text/03.Floating Windows @@ -0,0 +1 @@ +The How and Why of Floating Windows In the past few years it has become quite fashionable Ñ especially in imaging applications Ñ to support a new type of window whose behavior breaks all the rules of how windows were originally supposed to operate on the Macintosh: the floating window (sometimes called a ÒwindoidÓ). Floating windows always appear in front of standard windows, so that you can always see what information they convey; yet their presence in the foreground does not prevent operations from affecting the active standard window behind them. For the purposes of everything but visibility, they are effectively nonexistent. The onscreen appearance of a floating window is similar to that of a standard window, except for the floating windowÕs title bar, which is smaller and highlighted in a different manner. In general, floating windows use the terminology show and hide, rather than the more familiar open and close. This is reflected in the menu items relating to them: for instance, you can make the Statistics floating window visible by choosing the menu item labeled Show Statistics from the Windows menu; similarly, you can hide a floating window by choosing the Hide Statistics menu item from the same menu (it is in fact the same menu item, with the name changed as appropriate). When you make a floating window visible, one of the first things youÕll notice is that title bar of the topmost standard window is still highlighted, despite the existence of the floating window above it. This serves to remind you that the standard window is still really the ÒactiveÓ window and that all actions chosen from the menus will apply to the standard window and not to any of the floating windows. An important first example is that choosing Close from the File menu (or typing W) closes the active standard window, not the floating window. To hide (close) a floating window, you either choose Hide Window (where Window stands for the name of the floating window) from the Windows menu, or click in the floating windowÕs close box. Another important fact about floating windows is that they can never be manipulated such that they end up behind a standard window. That is, clicking in a standard window will bring the it in front of all other standard windows, but it will still appear behind any floating windows that are visible. Along the same lines, you can also click and drag to make a selection in the topmost standard window, without affecting the floating windows. At first, all this may seem a little disconcerting, but give it time and you will soon realize how useful floating windows can be. Finally, the position and visibility of each floating window is saved and remembered whenever you quit JPEGView, and is restored when JPEGView starts again. This means that you can position your floating windows and choose which ones to show, knowing that they will be visible in the same positions next time you run JPEGView. JPEGView currently supports three floating windows: the Statistics floating window, which displays information about the active image window; the Comments floating window, which is used to hold any comments extracted from the image in the active window; and the Colors floating window, which shows the current color selection on whichever monitor it is displayed. The slide show controls window is also a floating window; a description of its operation can be found in the Slide Show chapter. The Statistics floating window JPEGViewÕs Statistics floating window displays a host of useful information about the image currently displayed in the active window. To see this information, make the Statistics floating window visible by selecting Show Statistics from the Windows menu (0). Once visible, this floating window gives you a frequently updated list of many important bits of information about the currently active image and about how it is being displayed. Below is a summary of what each field describes and what you might find displayed there. If the list of data presented seems a little too extensive for your purposes, you can shrink it down to a one-line summary by clicking in the zoom box on the right side of the title bar. The format of the summary is: My Image: size format, width x height x colors where My Image is taken from the File Name field, size is taken from the Image Length field, format is taken from the Image Format field, width and height are taken from the Image Size field, and colors is taken from the Image Colors field. More details about what the values in each field mean are given below. Also, if you are running on a drag-aware system (System 7.5, or an earlier System 7 release with the Macintosh Drag and Drop extension installed), you can take advantage of the drag-and-drop functionality to drag the statistics information as text into another application. Statistics for the original image File Name: This is simply the name of the original file from which the image was read. Image Size: This tells you the width and height of the original image in pixels, before any scaling performed by JPEGView. For cropped images, this field tells you the size of the cropped region, with the original size given in parentheses immediately afterwards. Image Colors: This is the number of colors described by the image data, given in the same way youÕre used to seeing it in the Monitors Control Panel, i.e., ÒThousandsÓ means 32,768 and ÒMillionsÓ means 16.7 million. Image Status: This field tells you the ÒstatusÓ of the image, which can be a combination of: ¥ Aborted: the drawing of the image was interrupted (using the Esc key or the . combination). ¥ Banded: the image was compressed using QuickTime under low memory conditions. This means that the full image actually consists of several smaller images, each of which is a horizontal strip of the full image. ¥ Corrupt: the compressed image data was found to be damaged in some form or another. Portions of the image may still be decipherable. ¥ Cropped: the image is actually only part of a larger image; the full image can be recovered using the Uncrop Image function, described in the Special Effects chapter. Compression: This field tells you the type of compression used on the image and, if the information is available, the vendor of the compressor and the quality factor used in the compression. There are a number of possible values that can be found here: ¥ JPEG (QuickTime, Adobe, or I.J.G.) for JPEG images compressed by QuickTime, Adobe, or the Indepedent JPEG GroupÕs software, respectively. ¥ GIF/LZW for images compressed using GIFÕs variant of Lempel-Ziv-Welch compression. ¥ Modified CCITT RLE for TIFF images compressed using a variant of CCITT Group 3 fax compression. ¥ PackBits for MacPaint images or for TIFF images compressed using the PackBits RLE compression. ¥ LZW for TIFF images compressed using Lempel-Ziv-Welch compression. ¥ LZW with prediction for TIFF images using horizontal prediction together with standard LZW compression. ¥ 4-bit or 8-bit RLE for BMP images compressed using MicrosoftÕs RLE compression. ¥ Photo CD for images compressed using KodakÕs Photo CD technology. ¥ Photo Ñ JPEG for QuickTime PICT images compressed using AppleÕs JPEG compressor. ¥ Animation for QuickTime PICT images compressed using the Animation compressor. ¥ Graphics for QuickTime PICT images compressed using the Graphics compressor. ¥ Compact Video (or Cinepack) for QuickTime PICT images compressed using the Compact Video compressor. ¥ Video for QuickTime PICT images compressed using the Video compressor. ¥ Uncompressed for uncompressed images. For QuickTime-compressed PICT images, the quality factor used during compression is given, in the standard range from 0.00 (worst) to 4.00 (best). For JFIF images, which do not store the original quality factor used in compression, only an estimate of this quality factor can be made from the tables stored in the image. Currently JPEGView can only estimate the quality of JFIF files created by the Independent JPEG GroupÕs code, which uses a different quality scale than QuickTime, ranging from 0 (worst) to 100 (best). File Format: This is the file format that the image was saved in. Possible values include PICT, JFIF, GIF, TIFF, BMP, MacPaint, and Startup Screen. Image Length: This is the length of the image, given in kilobytes. If the image was compressed, then the savings gained by compression is computed and displayed either as a percentage for small compression gains (e.g., 60% compression, meaning that the compressed image is 60% smaller than the original) or as a ratio for highly compressed images (e.g., 7:1 compression, meaning that the compressed image is 7 times smaller than the original). Statistics for the displayed image Displayed Size: This is the width and height of the image you are actually seeing onscreen. If the image has been scaled, the scaling factor is given in parentheses as a percentage. If the horizontal scaling on the image is different from the vertical scaling, the scaling factor is given as two separate percentages, horizontal scaling first. Displayed Colors: This is the currently selected color set for the image, as seen in the Colors menu. Usually, JPEGView dithers images to ensure the highest quality display; if dithering is for some reason turned off, this is indicated as well. Display Quality: This is the quality used for drawing the image, if it was drawn on a screen with 256 colors or more. An explanation of what this quality means is given in the Colors and Color Reduction chapter. If the image was drawn on a screen with less than 256 colors, this field displays Òn/aÓ (not applicable). Display Time: This is amount of time it took for JPEGView to last draw the complete image, given in seconds. Note that this time is only updated when the image needs to be decompressed while the entire image window is visible on-screen; if the image is copied from an offscreen bitmap, this field is not affected. Offscreen Bitmap: If JPEGView has created an offscreen buffer for the current image, its size is displayed here; otherwise, it will read ÒNo bitmap.Ó Free Memory: This represents the amount of memory JPEGView has remaining. Note that, unlike previous versions, this takes into account the extra memory JPEGView sets aside for internal use (about 100k). Therefore, donÕt be worried if you see Ò0KÓ on this line Ñ more than likely, JPEGView still has a comfortable amount of memory to work in. The Comments floating window JPEGViewÕs Comments floating window allows you to view comments extracted from GIF files, JPEG files, and from JPEG-compressed PICT files. To make the Comments floating window visible, select Show Comments from the Windows menu (or type `). When the window appears, it will contain the text of the comments, or ÒNo comments foundÓ if the image contained no comments. The Comments floating window is also automatically resized to display the full text of any comments. JPEGView also provides a mechanism for automatically hiding and showing the Comments floating window depending on whether the active window has any associated comments. The Preferences Options chapter explains how this operates in greater detail. If you leave this option off, you can find out whether the active image contains any comments by looking for a diamond mark next to the Show Comments/Hide Comments menu item. Finally, like the Statistics floating window, you can drag the text out of the Comments floating window and into another application which supports drag and drop (assuming you are on a drag-aware system). The Colors floating window The last of JPEGViewÕs floating windows is the Colors floating window, which displays the current set of available colors on whichever monitor the window is currently residing. This is most useful on screens with 256 or fewer colors, where the selection of available colors becomes important for improving image quality. For screens with Thousands or Millions of colors, four smooth bands of red, green, blue, and gray are displayed, ranging from darkest to lightest. To make the Colors floating window visible, select Show Colors from the Windows menu (\). To hide it again, choose Hide Colors from the same location. As an interesting aside, the Colors floating window can be positioned across two or more monitors, in which case it will display the color set for the screen which can display the most colors. \ No newline at end of file diff --git a/Resources/Help Text/04.Special Effects b/Resources/Help Text/04.Special Effects new file mode 100644 index 0000000..edd9581 --- /dev/null +++ b/Resources/Help Text/04.Special Effects @@ -0,0 +1 @@ +Special Effects JPEGView provides a small number of useful on-screen manipulation tools that allow you to adjust the scaling factor of the active image, to perform cropping and zooming, or to make use of the full area of your monitor. All these features are described in detail below. The wonders of full screen windows The MacintoshÕs interface is very nice, what with the menu bar and windows and all, but sometimes donÕt you just wish that a 640x480 image could be displayed in full on your 640x480 display? When you account for the height of the menu bar plus the height of the windowÕs title bar, you find that youÕre losing a little less than 10% of your vertical resolution on a 13Ó monitor. (If the windows had scroll bars, youÕd be losing even more!) With JPEGView, you can gain this area back and view images to the full resolution of your screen simply by choosing the Full Screen option from the View menu (F). The Full Screen menu item acts to toggle the view of the current image between a normal window and a full-screen, menubar-less window. In case itÕs not obvious which sort of window youÕre currently looking at, you can check the View menu to see whether the active window is in a full screen window by looking for the checkmark next to this menu item. When a full screen window is in front, the menubar is hidden from view (this is, assuming the image window is on your menubar monitor). Although you cannot see the menus, all the standard -key shortcuts work just fine. In addition, by clicking anywhere inside the full screen window (but outside the current selection, if there is one), you can bring the menubar forward and access the menus in the usual manner. A second click inside the window will put the menubar away again. Several other actions can also force the menubar back to the front, including: closing the full screen window; selecting a normal (non-full-screen) window; and switching to another application. Selecting portions of an image in JPEGView You may have noticed that when you move the mouse pointer inside the window of the active image, the pointer changes to a crosshair. In JPEGView, as in most graphics applications, you can select an area of the active image by clicking in the image, dragging a rectangle around the desired area, and then releasing the mouse button to make the selection final. Once a selection is made, an animated dashed rectangle is displayed around the selected area. If you select an area less than 16 pixels in one direction, or simply click without dragging, the selection is canceled. Once youÕve made your selection, moving the mouse pointer around some move reveals yet another cursor: the hand cursor. When the mouse pointer lies within the selection rectangle, the pointer becomes a hand to indicate that you can drag the selection area anywhere within the image while preserving its original size. Note that in order to define a new selection rectangle, you must begin by clicking outside of the original rectangle; otherwise, JPEGView will think you want to drag the original selection around rather than begin a new selection. Use the cursor shape as your guide: if it is a crosshair, clicking will produce a new selection; if it is a hand, clicking will drag the current selection. Another intriguing option for making a selection is to use the Select Screen Area (A) option under the Edit menu. This creates a selection rectangle in the middle of the active image that is exactly the proportions of the monitor that image is displayed on, scaled in the same way as the image. That is, the selection that is created represents the area of the image you could view if the image were displayed unscaled on your screen. Once created, this selection rectangle can be dragged about the image like any normal selection. If this concept seems unclear, read on into the next section to find out how this can be used in conjunction with cropping and zooming to form a very powerful tool for examining images in more detail. After selecting a portion of the image, you are free to copy it to the clipboard, assuming you have enough memory available to do so. To give it a try, choose Copy (C) from the Edit menu. Because JPEGView often deals with very large images, it is easily possible that you will run out of memory during the copy operation; if this happens, you are probably best off copying the image in pieces and reassembling them by hand at the other end. Also note that if no selection is active, choosing Copy will attempt to copy the entire image. Similarly, on a drag-aware system, you can drag the selected portion of the image outside of its window and into another application which supports dropping pictures. Because JPEGView already allows you to drag selections within windows, this operates a little strangely: when the mouse pointer is displayed as a hand, you can drag the image anywhere within the image itself. However, once you drag the mouse pointer outside the bounds of the window, you will begin the drag-and-drop operation. At this point, the original selection is remembered, even if there was no target for the drop. Cropping and Zooming Once youÕve made your selection, you are ready to use one of JPEGViewÕs most powerful features: Crop & Zoom (R), located in the Edit menu. This option takes the area of the image that you have selected and creates a new window containing only that portion of the image. That takes care of the ÒCropÓ part. The ÒZoomÓ part comes in when JPEGView tries to make this smaller portion of the original image fit on your screen. If youÕve selected an area in the original that will fit unscaled on your screen, then it is displayed as such. If the cropped area is still too large, it is scaled to fit on your screen at the maximum size possible. The usefulness of this feature becomes apparent when used in conjunction with the Select Screen Area option. LetÕs say you long for the good old days, when scroll bars were in vogue and you could use your whole screen to look at the minute details in your images without having to see the image scaled down to 50% or whatever. Well, you can still do that! Just Select Screen Area on your image, drag the selection over the area you wish to examine, and then Crop & Zoom. The area you chose will expand to fill up your screen exactly Ñ and you didnÕt have to scroll around helplessly looking for the good bits. Once youÕve cropped an image, you can always return to the original full-size image by choosing Uncrop Image (U), again in the Edit menu, which will remove all cropping from an image and replace it with the complete original. Changing the scale factors The last of JPEGViewÕs special effects is the ability to play with the on-screen scaling of images. This can be accomplished in one of two ways: either by hand, by dragging the lower-right corner of the image; or automatically, by using the commands at the bottom of the View menu. The former technique is probably the more intuitive of the two. If you move your mouse pointer down into the bottom-right corner of the active image, you will notice that the cursor takes on yet another shape: that of a resizing box, which youÕre used to seeing in the bottom-right corner of windows in most other applications. Clicking and dragging the mouse while the cursor is thusly shaped will allow you to change the size of the current image. By default, the new size of the image is constrained to have the same ratio of height to width as the original; however, you can remove this restriction by holding down any of the modifier keys (Shift, Control, Option, or ). Your other options for adjusting an imageÕs onscreen size are accessible from the bottom half of the View menu, and all are relatively straightforward. You can double or halve the size of the current image with the Double Size (D) and Halve Size (H) menu items, respectively. Or you can force the image to expand to its maximum size on the current monitor with the Maximum Size (M) item; the zoom box in the upper right-hand corner of an imageÕs window will do this trick as well. For more precise scaling, you can increment and decrement the scale factor in steps of 10% using the Shrink by 10% ([) and Expand by 10% (]) options. And when youÕve finished playing with scale factors, you can select the Normal Size (L) option to return the image to 100%. Finally, for those with multiple monitor systems, there is the Resize to Screen (E) command, which will recompute the standard scaling for the image based on the size of its current monitor. This is useful, for instance, if you drag an image from a 13Ó monitor to a 19Ó screen and want to expand the image to its natural size on that screen. \ No newline at end of file diff --git a/Resources/Help Text/05.Colors & Reduction b/Resources/Help Text/05.Colors & Reduction new file mode 100644 index 0000000..f4f50d2 --- /dev/null +++ b/Resources/Help Text/05.Colors & Reduction @@ -0,0 +1 @@ +Colors and Color Reduction JPEG-compressed images, as well many PICT, TIFF, and BMP images, can contain a lot of color information Ñ 16.7 million colorsÕ worth, to be exact. This is just fine if you have 24-bit display hardware, capable of displaying in AppleÕs ÒMillionsÓ mode, but unfortunately we arenÕt all so lucky. The fact is that the single most popular color setup on the Macintosh is the standard 8-bit, or 256 color display. It may not be immediately obvious that you can, in fact, view 24-bit color images with rather high quality on a 256 color display. After all, how can you possibly go from 16.7 million colors down to 256 colors without losing something significant? Video modes on the Macintosh To understand how colors and color reduction work, it is necessary to understand something about the way the Macintosh handles its monitors. The current version of 32-bit Color QuickDraw, which is responsible for all drawing on your Macintosh, supports six different screen modes, depending on how much video memory (sometimes called VRAM) your Macintosh has available for the screen. These modes are identified by the number of colors that each pixel, or dot, on your screen can represent. There are the direct video modes (Millions and Thousands in the Monitors control panel), the CLUT (or indirect) video modes (256 and 16 colors), and the monochrome modes (4-color and Black & White). The direct video modes are so named because you can directly control the exact color of each pixel on the screen independently. When you look at a pixel on your color screen, what you are actually looking at are three dots of light superimposed on top of one other: one red, one blue, and one green. By varying the brightness of each of these three components, you can ÒcreateÓ virtually any color imaginable. Thus, you can say that red, green, and blue are the three ÒprimaryÓ colors of your monitor, in much the same way that red, yellow, and blue are the three primary colors of your watercolor set; if you combine them in just the right proportions, you can get any other color you want. In direct video modes, you specify for each pixel exactly how much red, blue, and green it should display on your screen. This gives you complete control over the final result. What then becomes important is how finely you can adjust the brightness levels of each of these components. In AppleÕs Thousands mode, you can specify one of 32 possible brightness levels for each component, red, green, and blue, giving you 32 x 32 x 32 = 32,768 colors total. In Millions mode, you get to choose one of 256 possible brightness levels for each component, or 256 x 256 x 256 = 16,777,216 colors. When you scale back to the 256-color and 16-color video modes, this direct control over the color components isnÕt nearly as effective, since you would only be allowed at most 6 or 7 possible brightness levels in each component. The MacintoshÕs solution to this problem lies in its use of color lookup tables (CLUTs). A CLUT is a small table of colors (with 256 or 16 entries, in this case) chosen from any of the 16.7 million colors available in the Millions mode. To display one of these colors, the Macintosh gives the display hardware a color index, say, from 0 to 255, which is then used to pick a corresponding color from the CLUT to display on your screen. This way of doing things gives you tremendous flexibility in choosing your colors. For example, on a 256-color system, you can design a color set with 256 levels of grayscales for your display just as easily as you can design a color set with 256 colors chosen at random from the 16.7 million available. Of course, what you would obviously prefer is the ability to choose the optimal set of 256 colors for displaying a given image, and this is exactly what JPEGViewÕs two-pass color reduction feature does for you. Finally, I should admit that the 4-color mode is also technically a CLUT mode, even though I called it a monochrome mode before. The reason I grouped it in with the black & white mode is that your Macintosh requires every display to be capable of showing black and white, which leaves only 2 colors that are truly free to be chosen. Since you canÕt even get the essential red, green, and blue with those 2 colors, it is best simply to choose two intermediate grayscales to give you the highest-quality image, leaving you with a monochrome display. JPEGView and color sets If at least one monitor in your system setup is operating in one of the CLUT modes Ñ either with 16 colors or with 256 colors Ñ then you can use JPEGViewÕs Colors menu to select a new color set for the current image. There are currently four different color sets available: the System Colors (Y), the Grayscales (G), the Image Colors (J), and the color set produced with Two-Pass Color Reduction (T). The first two options Ñ the System Colors and the Grayscales Ñ are color sets that youÕre probably familiar with already, though you may not have known it. The former is simply the set of colors that youÕre used to seeing when youÕre in the Finder, while the latter is what you see when you switch your monitor into Grayscales mode in the Monitors control panel. To see what sort of color selection is provided by these or any other sets of colors in JPEGView, you can make the Colors floating window visible. As you switch color sets within JPEGView, the colors displayed in the floating window will change to reflect the new set of colors. Some images that you load with JPEGView, in particular GIF images, contain a color set internally, defining which colors should be used to display the image. If JPEGView finds such a color set within an image, it will allow you to choose those colors via the Image Colors item in the Colors menu. If no color set information is provided with the image, this menu item will not be available. Finally, for images that contain Thousands and Millions of colors, JPEGView provides the ability to generate a custom color set for the image, produced by examining the distribution of colors within the image. This is known as two-pass color reduction (sometimes called color quantization), for the simple reason that JPEGView must first scan through the entire image once to determine the proper color set, and then the image must be scanned a second time during the actual display process. For the other color sets available, the display process only requires one pass through the image. Two-pass color reduction will very nearly always give you far better results than any of the other color options. The main downside to this feature is that it simply requires more time to display an image. JPEGView leaves the default choice up to you; see the Preferences Settings chapter for more details on how you can control this behavior. In addition, for JFIF and PICT images, once you have performed two-pass color reduction, JPEGView allows you to save the calculated color set information with the image, so that you donÕt need to perform the calculation again. The chapter Saving Images explains how you can do this. Dithering Ñ how and why it works No matter which color set is selected, you also have control over whether or not to dither the resulting image via the Dithering item in the Colors menu (B). Dithering is a technique that ÒsimulatesÓ colors that arenÕt available in the current color set by modifying the colors of the surrounding pixels. As a simple example of how dithering accomplishes this feat, consider a random pixel in an image, whose color is supposed to be purple. If the current color set contains a color that exactly matches that purple, that particular color is chosen, and there are no problems; dithering has no net effect. But imagine a color set had no purples at all, but did have shades of red and blue. Without dithering, that purple pixel would appear as a red pixel, since red is the closest match we can get to purple with the current (red and blue) set of colors; unfortunately, this wonÕt look very purple in the end. Now turn dithering on. Dithering finds the closest match Ñ red Ñ just as before, but then it looks at the difference between this closest match and the original color we wanted. In this case, dithering would notice that there should have been more blue in this pixel, and, to compensate for this loss, it would add a little bit of blue to the neighboring pixels. Now imagine that one of these neighboring pixels, whose blue component has just been increased, was originally the same purple as the original pixel. With the adjustment, it is now a rather bluish-purple color. So, when it comes time to find the closest match to this new color, we will choose blue rather than red, because blue is closer to bluish-purple than red is. Again, we calculate the difference between the chosen blue color and the original color we wanted (bluish-purple), and see that some red was missing. Dithering will thus add a little bit of red to pixels surrounding this one, and proceed on to the next pixel, continuing this for all the pixels in the image. In the end, an area of solid purple Ñ which cannot be displayed as such with our example blue and red color set Ñ will appear as a pattern of alternating blue and red dots, which will actually give the appearance of purple if you donÕt look too closely. In this way, dithering approximates colors by finding what was missing in the current pixel and distributing that difference to the surrounding pixel. The advantage of dithering is that it effectively simulates more colors than your monitor can actually produce. The disadvantage is that the image comes out a little less distinct, and can sometimes suffer from dithering artifacts. The next section discusses this latter problem in more detail. Scaling, dithering, and display quality The MacintoshÕs 32-bit QuickDraw, which is the highly-optimized system responsible for all drawing operations that occur on your system, supports the ability to automatically perform dithering and scaling operations on an image. This functionality makes it very easy to incorporate such features into an application program, and for most operations, it does an excellent job. However, there are some limitations in QuickDrawÕs dithering that only become apparent when displaying images on 256-color screens using two-pass color reduction. The problem is that the dithering algorithm used by QuickDraw works best when the available color set is not very well matched to the colors that are in an image, e.g., when an image is displayed with only 16 colors, or with 256 colors using the system colors. When the available colors are a good match for the image colors, however, QuickDrawÕs dithering can produce dithering artifacts, or strangely discolored areas in the image. In order to fix this problem of dithering artifacts, JPEGView implements its own dithering algorithm, which remedies the problem for most images. Unfortunately, in order to support its own dithering, JPEGView must also support its own scaling, since the two operations are intricately coupled. Although JPEGViewÕs high-quality dithering algorithm itself is fast Ñ almost as fast as QuickDrawÕs built in dithering Ñ JPEGView does not know how to scale an image as fast as QuickDraw. Because of this, JPEGView supports two forms of scaling, in addition to QuickDrawÕs own routines. Selecting which set of routines to use for drawing is accomplished through the Quality menu, available under the Colors menu. Three options are available: Very High quality (Shift-V), High quality (Shift-H), and Normal quality (Shift-N). These options are only useful (and only available) if the image is drawn on a screen with Thousands or more colors available, or on a screen with 256 colors if the image is drawn using either two-pass color reduction or the image colors. In all other situations, the normal QuickDraw drawing is used. What JPEGView calls Normal quality drawing is simply QuickDrawÕs standard routines, which give fast results with the possibility of the dithering artifacts mentioned above on 256-color screens. Normal quality is also used when the current color set does not match the imageÕs colors very well, since QuickDrawÕs dithering does a fine job in this situation. High quality drawing combines JPEGViewÕs improved dithering with a fast, but relatively coarse, scaling algorithm. For most purposes, this fast scaling does a good job, and even gains you a small speed gain over the QuickDraw scaling youÕre used to. High quality drawing is only available on 256 or Thousand-color screens; those with Millions of colors available wonÕt notice any dithering difference, and the scaling is visually a little worse than standard QuickDraw scaling, making High quality into a net loss over Normal quality for such users. Very High quality drawing takes JPEGViewÕs improved dithering and adds a slower, but very accurate scaling routine. For those with an eye for detail, the scaling used in Very High quality drawing is often better than standard QuickDraw scaling, making this quality level useful for those with Thousands and Millions of colors as well. Note that when an image is not scaled, High quality and Very High quality are identical, since the difference lies only in the scaling algorithm used. To help see the difference that JPEGViewÕs improved dithering can make, try opening the ÒParrots JPEGÓ image that was included with JPEGView. View it using both Normal and High quality on a 256 color screen with two-pass color reduction turned on; the difference should be clear. Note that ÒParrots JPEGÓ is an extreme example of the problems encountered with QuickDrawÕs dithering; donÕt expect such dramatic improvements on all images! \ No newline at end of file diff --git a/Resources/Help Text/06.Saving Images b/Resources/Help Text/06.Saving Images new file mode 100644 index 0000000..3c0c16e --- /dev/null +++ b/Resources/Help Text/06.Saving Images @@ -0,0 +1 @@ +Saving Images Although JPEGView has been designed primarily as an image viewer, it also sports the ability to resave images with QuickTime previews and custom Finder icons. In addition, JPEGView can perform the very simple conversion between the standard JFIF format and the MacintoshÕs own JPEG-compressed PICT format, allowing you to save most JPEG-compressed images in either format. File formats in the Save dialog When you choose the Save As item from the File menu, you are presented with a standard save file dialog, with a few extra options appended to the bottom. Anything that looks familiar works as usual. The remaining options allow you to choose the output file format or to include additional data with the image file. Additionally, by checking the ÒClose when finishedÓ box, you can instruct JPEGView to immediately put away the image after it has finished saving it, thereby avoiding any long window updates that might follow. If you are saving an image that has been compressed using JPEG, the file format popup menu will offer you several choices, allowing you to save your image in one of the three output file formats that JPEGView supports: JPEG-compressed PICT, JFIF, and PICT Resource. More details concerning the properties of the PICT and JFIF file formats can be found in the File Formats and File Types chapter. The oddball format available here is the PICT Resource format, which is useful mainly for saving JPEG-compressed PICT images in a useful format for programmers. Also, please note that any PICT image which is ÒbandedÓ, that is, made up of several small JPEG images sewn together, cannot be saved as a JFIF file. Banded PICT images are sometimes produced by QuickTime whenever memory space is low. Since the JFIF image format was designed to store only a single image, a banded PICT cannot be converted to JFIF without decompressing the composite image and recompressing it as a single image. JPEGView does not support this sort of functionality. If the image you are saving has not been JPEG-compressed, then you will have to save it in its original format, and there will be no popup menu for you to choose from. However, you will still have the luxury of choosing to add QuickTime previews and/or custom color Finder icons to the image for future ease-of-use. Saving modified images In addition to simply allowing you to save the image data out to a file, JPEGView also allows you to save cropping information, QuickTime preview images, custom Finder icons, and color reduction with your image. There are two ways to get JPEGView to save the cropping information with an image. The most straightforward is simply to crop the image in JPEGView, and then choose Save As from the File menu with the cropped image frontmost; when saved, the cropping is retained. Alternatively, you can select the portion of the image you wish to crop to, and then issue the Save As command. When you do this, the popup menu at the bottom of the dialog will be enabled, allowing you to tell JPEGView to ÒUse selection to crop ImageÓ. If you have checked the ÒInclude preview (thumbnail) imageÓ box, JPEGView will create a preview image. This preview image is simply a smaller representation of the full image, allowing you to quickly see what the image is without having to decompress the whole thing first. QuickTime automatically supports viewing of these preview images in the Open dialog for all formats except JFIF. The ability to view JFIF previews can be added to QuickTime by placing the JPEGView JFIF Preview extension in your Extensions folder. See the chapter Viewing Images for more details on viewing JFIF previews. JPEGView also supports the creation of custom icons for saved images. This option extracts a portion of the image (selectable in the Preferences) and shrinks it down to the size of a Finder icon, adding this information to the saved file. The resulting document will then appear in the Finder not with the standard JPEGView icons (which are pretty cool to begin with), but with this postage stamp-sized icon instead. If you have a color system, this might enable you to guess which image you would see if you double-clicked the icon. Sometimes it is convenient to be able to specify a smaller portion of the image from which to take the icon data. JPEGView allows you to do this by simply selecting the subsection of the image you want, and then choosing ÒIconÓ from the ÒUse selection to crop...Ó popup menu at the bottom of the Save dialog. This will instruct JPEGView to use the selected area of the image for the icon, while leaving the entire image intact (to crop the image as well as the icon, choose ÒImageÓ from the popup menu). JPEGViewÕs color reduction information can also be included whenever you save a JPEG-compressed image. What this means is that when opening this image in the future, JPEGView and certain other image viewers can detect and make use of this information without having to slog through the time-consuming color reduction. When you open the image with JPEGView specifically, this information serves to define the Image Colors, which JPEGView will automatically use. The final result Once you have entered a filename and have chosen your desired options, click on the ÒSaveÓ button to perform the operation. If you chose to create a preview or icons, a progress dialog will appear to keep you updated on the status of JPEGViewÕs work; otherwise, JPEGView will perform the save operation quickly and quietly. \ No newline at end of file diff --git a/Resources/Help Text/07.Slide Show b/Resources/Help Text/07.Slide Show new file mode 100644 index 0000000..54dc1ee --- /dev/null +++ b/Resources/Help Text/07.Slide Show @@ -0,0 +1 @@ +Slide Show One of JPEGViewÕs more powerful features is its ability to display an entire folderÕs worth of images in a slide show. Unfortunately, everybody seems to want their slide show to operate differently than everyone elseÕs, which is the reason why JPEGView presents you with so many options when you bring up the Slide Show Options (via the File menu or the I key combination). Fortunately, though, you never need to mess with most of them! Slide shows for beginners The concept of a slide show is simple: first, you need to choose a group of images to view; and second, you need to decide who controls the JPEGView projector. In regard to the first decision, JPEGView allows you to choose one of two possible sources for your images: either from memory or from disk. The simplest way to see a slide show is to open up several images in JPEGView and choose ÒImages from MemoryÓ from the pop-up menu on the right-hand side of the Slide Show Options dialog. This tells JPEGView that it should choose its slides from among those that youÕve opened. Your other option is to instruct JPEGView to choose from image files that reside on your disk. Running in this mode of operation requires an extra step, in addition to choosing ÒImages from DiskÓ from the rightmost pop-up menu. Inside the box governed by this pop-up menu is a large button which reads ÒSelect Slide Show FolderÓ. Clicking on this button will bring up a dialog box which will allow you to select a folder; its operation is pretty self-explanatory. Once a folder has been selected, its full path will be displayed below the button. An alternative Ñ and simpler Ñ method of selecting the slide show folder is available if your system is drag-aware (running System 7.5 or an earlier System 7 release with the Macintosh Drag and Drop extension and Finder 7.1.2 or later). Rather than navigating through a dialog to choose the slide show folder, you can simply drag any folder or alias from the Finder into the Slide Show Options window. As you do this, the window will become highlighted, and when you release the mouse button, the folder will change to the one you dragged in. After choosing the source of the slide show images, you must then decide who retains control of the switching between slides, either you or JPEGView. The pop-up menu on the left-hand side of the Slide Show Options dialog allows you to control this aspect of the slide show. Choosing ÒUser-controlledÓ from the pop-up menu tells JPEGView to wait for you to explicitly command it before proceeding on to the next slide. Your other choice is to give JPEGView complete control of things, by selecting ÒAutomaticÓ from the leftmost pop-up menu. Doing this enables the two items in the box below the pop-up menu, allowing you to specify the minimum time interval between successive slides. Use the newly-enabled pop-up menu to choose the units Ñ either seconds, minutes, or hours (?!) Ñ and type the appropriate number in the box to its left. Once youÕve selected these basic options, youÕre ready to proceed. Click the ÒBeginÓ button to start up the slide show immediately, or simply close the window to save your changes but postpone the beginning for later. If, for some reason, the ÒBeginÓ button is dimmed, it means that JPEGView can no longer find the folder you selected; to remedy the situation, either choose another folder or insert the disk that the folder resided on. The other button, ÒRevertÓ, restores the settings to what they originally were when you first opened the Slide Show Options dialog. Finally, the slide show can be initiated directly from the File menu by choosing Begin Slide Show, or by typing I while holding down the Shift key. This causes the slide show to be run with the last settings you chose in the options dialog. Help! WhatÕs going on?! Once begun, JPEGViewÕs slide show proceeds inexorably forward until you manage to stop it (or, optionally, until it finishes cycling through all the images). As each image is displayed, the next image is prepared in the background. Because this preparation can sometimes take longer than the automatic slide show delay, it is useful to know whether JPEGView is still preparing the next image or just waiting for the delay to pass. While it is busy preparing the next image for display, JPEGView provides three indicators that you can use to tell that it is busy. The first is the familiar spinning busy cursor, visible at all times in user-controlled slide shows, or visible by moving the mouse in automatic slide shows. In addition, JPEGView displays a small white progress dot in the upper-right corner of the screen where the images are displayed. As things progress, the little dot rotates around to indicate that everything is still chugging away. The third indicator is provided in the status line of the Slide Show Controls floating window, if it is currently visible on the screen. If it isnÕt immediately visible when the slide show begins, simply click the mouse button anywhere outside of a floating window to make it appear. A second click will make it disappear again, clearing it out of the way of any image displayed underneath the controls. You can control whether the controls window is visible through an option in the Slide Show Options dialog; see below for more details. The status line of the Slide Show Controls floating window serves as a running commentary of JPEGViewÕs current operations. Here is what you can expect to see on this line: ¥ Loading: file. JPEGView is reading the file named file from disk. ¥ Reducing: image. JPEGView is performing two-pass color reduction on image. ¥ Rendering: image. JPEGView is currently drawing image offscreen. ¥ Drawing: image. JPEGView is drawing image onscreen. ¥ Ready. JPEGView has finished its preparations for the next image and is waiting for you to manually advance (user-controlled slide show only). ¥ Delaying... seconds. JPEGView has finished its preparations for the next image and is killing time before displaying it, with seconds seconds remaining (automatic slide show only). ¥ Paused. The slide show is currently paused. Let me off this crazy thing! As JPEGViewÕs slide show progresses, you have the opportunity to control its progress, either through the push-button controls available in the Slide Show Controls floating window, or through keyboard shortcuts provided to mimic these controls. Currently, there are four push-button controls available: forward, reverse, stop, and pause. Exactly what happens when you activate any one of these controls is described below. Forward. This button is generally used to advance the slide show forward by one slide whenever JPEGView has finished preparing the next slide (that is, when the status line is displaying either ÒReadyÓ or ÒDelaying...Ó). If you press this button while JPEGView is still busy, it will activate and stay depressed until JPEGView is finished with the next slide, at which point it will advance to it immediately. To make matters simple, just think of the forward button as meaning Òadvance to the next slide as soon as youÕre ready.Ó To perform this operation from the keyboard, or when the Slide Show Controls are not visible, simply hit any key other than those that are reserved for the other functions below. The space bar, right arrow, and Enter keys are popular choices. Reverse. Use this button to back up one slide in the slide show, relative to the slide that is currently displayed on the screen. Note that the reverse function may be disabled if the first slide in the list is being displayed (since there is nowhere to back up to!) You can also use the left arrow key on the keyboard to back up in the same way. Stop. Click this button to stop the slide show immediately, leaving the last image displayed on screen. When you do this, the Slide Show Controls floating window will disappear, and any previously visible floating windows will be shown again. The keyboard equivalents for this function are the Escape key (esc) or . (that is, type the Ò.Ó (period) key while holding down the  key). Pause. Use this button if you want to temporarily pause the slide show. When first activated, the Slide Show Controls floating window is automatically made visible, and the menu bar is displayed. You can then switch to other applications, end the slide show, modify some (not all) of the slide show options, or do whatever else you care to do before resuming the slide show. When you switch back to JPEGView, simply click the depressed pause button again to resume the slide show where you left off. Note that JPEGView may need to reload and reprocess the next image, depending on exactly where you interrupted processing. JPEGView also supports an extension to the paused slide show which allows you to not only pause but also hide all traces of the slide show. If you hold down the Option key as you click the pause button, JPEGView will automatically hide all of its slide show windows and send itself into the background. To resume after this happens, simply bring JPEGView back to the front by selecting it from the application menu on the far right side of the menubar. JPEGView will make its windows visible again, and you will be back in standard pause mode; clicking on the pause button will resume where you left off. To pause the slide show from the keyboard, you can use the up arrow key. Hiding and pausing the slide show can be accomplished by holding down the Option key as you type the up-arrow. Finally, please note that the response to your commands Ñ both mouse-based and keyboard-based Ñ will very often not be immediate, so give JPEGView a couple seconds before getting violent. Playing with the options Unless you tell it otherwise, JPEGView takes all your selected slides, mixes them up in a random order, and then displays them over and over again until you interrupt the slide show. However, using JPEGViewÕs Slide Show Options dialog, you can customize the operation of the slide show to suit your own purposes. Below is a list of all the available options, along with a description of what each optionÕs effects are. Display in random order (default setting is on). Turning this option on tells JPEGView that you would like to see the slides in a completely random order, rather than in their natural order. Turning it off leaves the slides in their natural order. For a memory-based slide show, the natural order is the order you see the files in the Windows menu; for a disk-based slide show, this natural order is the order they were found on disk, usually alphabetical within each folder. Repeat indefinitely (default setting is on). Checking the box next to this item will cause JPEGView to cycle through the slide show until interrupted by the user. If the ÒDisplay in random orderÓ checkbox is also checked, the slides will be randomly reordered before each cycle. If this box is left unchecked, JPEGView will end the slide show after a single cycle and display an alert telling you it has finished. Ignore any minor errors (default setting is on). With this box checked, JPEGView will quietly ignore any minor errors that occur when loading slide show images. ÒMinorÓ errors include corrupt image warnings, low memory conditions, and the like. It is possible that leaving this option on can cause some images not to be displayed during a slide show; if this is the case, you should turn this option off and see which errors are causing the problem. Hide floating windows (default setting is on). Turning this option on automatically hides any visible floating windows for the duration of the slide show. Otherwise, the floating windows will remain visible, floating above the images as they are displayed. Note that floating windows enjoy special status during a slide show: they can be shown, hidden, and moved about without interrupting the slide show or proceeding onto the next slide. To toggle the visibility of a floating window, simply use the appropriate -key shortcut; to drag a floating window, just drag it as usual, but note that this will only work when the cursor is a standard arrow shape! Hide slide show controls (default setting is off). Use this option to control whether the Slide Show Controls floating window is displayed at the start of the slide show. If this box if checked, no window is displayed; however, access to the window is still enabled through mouse clicks during the slide show. Leaving this box unchecked displays the Controls floating window immediately when the slide show begins. Automatically show comments (default setting is off). Checking this option gives control over the visibility of the Comments floating window to JPEGView, meaning that it will automatically appear whenever comments are found for the current image. If this option is left off, the Comments floating window remains under user control. Display filenames (default setting is on). Turning this option on displays the name of each image file in the lower right-hand corner of the image. If there is enough room either below the image or to the side of the image, the name is displayed there; otherwise, the file name obscures the corner of the image. With this option off, there will be no indication of which file is currently displayed. Options for disk-based slide shows The following options are only meaningful for slide shows based on disk images. If you have selected a slide show from memory, these options will all be unavailable. Scan subfolders recursively (default setting is off). If you check this option, then JPEGView will not only display all the files in the folder youÕve selected, but will also scan any folders contained inside the selected folder, as well as folders within those folders, etc. In fact, you could even select the Desktop with this option checked, and JPEGView would happily scan all the folders on all mounted drives for images. (I donÕt really advise this, however!) Turning this option off means that the search is limited to files within the selected folder only. Import unrecognized files (default setting is off). Checking this option causes JPEGView to add to its list of slide show images any files it finds in the selected folder, no matter what type of file the Finder says it is. As with the Import feature in the File menu, this is for the most part only useful to those with CD-ROM drives that have lots of incorrectly typed files. Leave this option off if you want to only open images whose file types are correct. Decompress offscreen (default setting is on). With this box checked, JPEGView attempts to completely process the next image offscreen Ñ including both color reduction and drawing Ñ before removing the current image. The success of this option is highly dependent on how free memory you have in your system. If there is not enough memory to draw the next image offscreen, it will have to be decompressed and drawn onscreen, meaning that more free memory will give you smoother transitions between slides. If you leave this option off, JPEGView will decompress and draw every image onscreen (though color reduction is always done offscreen during a slide show). \ No newline at end of file diff --git a/Resources/Help Text/08.Preferences Settings b/Resources/Help Text/08.Preferences Settings new file mode 100644 index 0000000..92eeead --- /dev/null +++ b/Resources/Help Text/08.Preferences Settings @@ -0,0 +1 @@ +Preferences Settings JPEGView provides a number of options for controlling how it handles images by default. These are collectively known as the preferences options, and can be accessed via the Preferences menu item in the File menu. The different settings are grouped into five categories Ñ Windows, Drawing, Bitmaps, Files, and Miscellany Ñ and you can select which set to modify via the pop-up menu near the top of the Preferences dialog. As you make changes to the options, they take effect immediately; close the preferences dialog to save the changes to disk. Each category and its corresponding options are described in detail below. Windows preferences The settings in this category allow you to control JPEGViewÕs use and placement of windows when opening new images. Open new images on theÉ (default is Deepest screen). These settings allow you to choose which monitor JPEGView uses for opening new images: Deepest screen. This is the screen that is capable of displaying the most colors. Largest screen. This is the screen that has the largest number of pixels. Main (menubar) screen. This is the screen that has the menubar. Of course, if you have only one screen, this option doesnÕt affect anything; it is primarily for choosing among multiple monitors on a Òtwo-headedÓ system. Color screens preferred (default is on). In conjunction with the screen selection above, this option lets you choose color screens over black & white/grayscale screens whenever a conflict occurs. For instance, if you chose Largest screen above, and had two monitors connected which were the same size, this option would let you choose either the color or the grayscale monitor first (assuming of course that they werenÕt both color or both grayscale!) Use full screen windows for new imagesÉ (default is Ask first for large images). This setting controls how JPEGView handles the automatic use of full screen windows: Always. Use a full screen window for every image opened, no matter what its size. Always for large images. Use a full screen window for any image taller than the height of your screen. Ask first for large images. Ask to use a full screen window for any image taller than the height of your screen. Never, even for large images. Never use a full screen window for any image opened, no matter what its size. Expand small images to maximum size (default is off). This option lets you choose the normal size of any image smaller than the screen it is displayed on (including small images produced from cropping). With this option off, these images are simply displayed at their original size, with no scaling. Turning this option on automatically expands these images to their largest possible size on the screen whenever they are created. Allow only one open image at a time (default is off). This option allows you to insist that there be only one image open at any given time. With this option turned on, JPEGView will automatically close all open images before loading in any additional images. This helps keep your desktop clear of multiple images and saves you the trouble of closing every image manually before opening a new one. Leaving this option off allows you to open multiple images simultaneously without any hassle. Drawing preferences These preferences options control exactly how JPEGView chooses colors and handles drawing images when you open them. Display quality (screens with 256 or more colors)É (default is High). This setting controls the drawing quality for newly-opened images: Very high. Selects the highest-quality display, using JPEGViewÕs custom dithering and high-resolution scaling algorithms. High. Selects a high-quality display, using JPEGViewÕs custom dithering and faster scaling algorithms. Normal. Selects normal-quality display, using the QuickDrawÕs built-in dithering and scaling algorithms. For more information on these quality settings, check out the Colors and Color Reduction chapter. Note that these quality settings only affect color displays with 256 or more colors, and that high-quality only works on 256-color displays. For this reason, the quality setting reported by JPEGView may actually be lower than what you set here. Never do slow background updates (default is on). This setting lets you disable slow window updates when JPEGView is not the active application. When this option is checked, obscured image windows that have no offscreen bitmap will remain displayed as a pattern of dots until you bring JPEGView to the front again. Turning this option off will allow these updates to proceed normally, possibly delaying other applications. Automatically reduce images to 16 or 256 colorsÉ (default is Only if no image colors are found). These settings let you control when JPEGView performs two-pass color reduction on newly-opened images: Always. Performs two-pass color reduction on every image where it is applicable, even if the image has its own color set. Only if no image colors are found. Performs two-pass color reduction on an applicable image only if the image has no color set defined with it. Never. Never performs two-pass color reduction on any image. The use of two-pass color reduction is limited to Òhigh-colorÓ images, that is, images containing Thousands or Millions of colors, and then only when they are displayed on screens with 256 or 16 colors. Dither reduced color images (default is on). This option gives you control over JPEGViewÕs dithering whenever two-pass color reduction is used on an image. Because two-pass color reduction usually does such a good job of choosing colors, you may find that dithering is unnecessary. If this box is checked, images displayed with two-pass color reduction will always be dithered. If this box is left unchecked, then these images will be left undithered. Use image colors, if available (default is on). This checkbox controls JPEGViewÕs use of image colors. When image colors are found stored with the image data, JPEGView will automatically use them for displaying the image if this option is checked. Otherwise, the standard system colors or two-pass color reduction (whichever is appropriate) will be used. Restore colors when closing last image (default is on). This option lets you instruct JPEGView to automatically restore the system colors whenever the last open image is closed. With this option off, closing the last image may leave the system in a somewhat discolored state. But turning this option on will tell JPEGView to manually reset the colors after closing the last image. The main disadvantage to this is that everything on the desktop will need to be redrawn in the new color set. Bitmaps preferences The items in this section control how JPEGView maintains its offscreen bitmaps, which are used for fast window updating. Offscreen bitmaps areÉ (default is Optional, if memory is available). These settings control JPEGViewÕs creation of offscreen bitmaps. Always required. Requires offscreen bitmaps for all new images. If an image can be loaded, but no bitmap can be created, JPEGView will not allow you to open the image and will give you an out of memory error. Further, once the bitmaps are created, they cannot be deleted to make room for other operations to proceed. Optional, if memory is available. Makes offscreen bitmaps an optional feature, contingent on there being enough memory to create them. If more memory is needed for another operation, existing bitmaps can be deleted and later recreated. Never created. Eliminates the use of offscreen bitmaps altogether. Not recommended for most users. Maintain bitmaps at imageÕs original size (default is off). This option lets you choose to create all offscreen bitmaps at the imageÕs original size. Normally, JPEGViewÕs bitmaps are just large enough to display whatÕs on your screen, meaning that screen updates are fast but that operations such as resizing, cropping, and preview and icon creation require that the image be decompressed again to make use of the full size and color resolution of the original. With original size bitmaps enabled, however, these operations become very fast because the full-resolution image data is already available. The main downside is that window updates of scaled images are slowed down because the scaling and dithering operations need to be performed to draw the correctly-sized image from the full-size original. DonÕt use bitmaps for uncompressed images (default is off). This checkbox controls whether JPEGView creates offscreen bitmaps for images that are uncompressed. Because uncompressed images are usually quick to display, it can save memory if you check this box to tell JPEGView that such images donÕt need the benefits of offscreen bitmaps. Otherwise, uncompressed images will be treated just as any other image, as far as offscreen bitmaps are concerned. Files preferences These options control automatic file type fixing and default options in the Save dialog. Automatically fix incorrect file types (default is on). This option is used to enable JPEGViewÕs automatic file type fixing feature, which is simply a quiet means of keeping file types straight without your intervention. With this option checked, for example, opening a JPEG file that is incorrectly identified as a GIF will cause JPEGView to automatically change the fileÕs type to JPEG. Without this option, the file types would remain confused, and could affect the ability of other applications to correctly identify your images. Change fixed filesÕ creator to JPEGView (default is off). This option is an extension of the previous option which causes the creator of any file whose type was automatically fixed to be changed to JPEGView. In practice, what this means is that the image fileÕs icon will become a JPEGView icon, and that the Finder will in the future open JPEGView whenever that image file is double-clicked. On the other hand, leaving this option off will preserve the fileÕs original creator, meaning that images created in other applications will still be associated with their original applications. Save reduced color informationÉ (default is Only if no image colors were found). These settings control how the ÒInclude reduced color setÓ checkbox is set up when the Save dialog is opened an output format which supports reduced color sets is selected. Always. Ensures that the ÒInclude reduced color setÓ checkbox is always selected. Only if no image colors were found. Selects the ÒInclude reduced color setÓ checkbox only if the image had no image colors stored in the original data. Never. Always leaves the ÒInclude reduced color setÓ option unchecked. Save in PICT format by default (default is on). This option lets you control which format will be chosen by default whenever an image file is saved. Turning this option on causes the PICT format to always be selected when the Save dialog is presented. Otherwise, the format selected in the Save dialog is the same format as that of the original file. Include previews with saved images (default is on). This checkbox controls the initial setting of the ÒInclude preview (thumbnail) imageÓ box in the Save dialog. If this option is enabled, then the corresponding checkbox in the Save dialog will be checked by default whenever the output file format is PICT or JFIF. Otherwise, the ÒInclude preview (thumbnail) imageÓ box will be left off when the Save dialog is presented. Compress JFIF preview images (default is on). This setting controls the use of compression when creating preview images for JFIF files. Turning this option on means that JFIF previews are compressed using JPEG before being stored in the image data; if this option is off, JFIF previews are left uncompressed. Although compressed previews are a more recent addition to the JFIF standard, they are stored in such a way that any JPEG decoder that follows the rules should be able to handle them. For compatibilityÕs sake, however, this option lets you create the old-style previews as well. Also note that PICT previews are always compressed by QuickTime, so there is no corresponding option for them. Create custom icons when saving images (default is off). This option sets up the ÒCreate custom preview iconsÓ checkbox when the Save dialog is presented. If this option is on, the ÒCreate custom preview iconsÓ option will be automatically selected in the Save dialog; otherwise, the corresponding option in the Save dialog will be initially turned off. Icon Style (default is square, dog-eared). This popup menu allows you to choose your preferred style for custom Finder icons. If you choose square icons, then JPEGView will extract the largest square area from the center of the icon and shrink that down into an icon; in contrast, proportional icons are scaled to dimensions proportional to the original image. In addition, if you choose a dog-eared style, then JPEGView will fold over the upper-right corner of the iconÕs image. Miscellaneous preferences These preferences settings control the JPEGViewÕs behavior in various other situations. On startupÉ (default is Present the Open dialog). These settings control what actions JPEGView takes when it initially starts up. Note that these actions only apply if you launch JPEGView directly by double-clicking the JPEGView icon. If you launch JPEGView by double-clicking a document icon or by dropping a document icon onto the JPEGView icon, these actions will not be taken. Repeat the last slide show. Causes the last slide show to be immediately repeated without your intervention. Present the Slide Show Options dialog. Opens the Slide Show Options dialog, giving you the opportunity to set up a slide show right away. Present the Open dialog. Opens the Open dialog, allowing you to select an image file right away.. Do nothing. Does nothing at all. Automatic Comments window control (default is on). This option determines who retains control of the Comments floating window. Enabling this option means that JPEGView is in ultimate control of the Comments floating window. In this situation, JPEGView will automatically make the comments visible whenever the active image contains comments, and will automatically hide the Comments window if no comments are available. Turning off this option returns full control of the Comments floating window to you. Time given to other applicationsÉ (default is Reasonable). These settings let you specify how much time JPEGView gives to other applications while it is decompressing an image for display. Maximal. Selects the maximum amount of time JPEGView is willing to give up. Note that this will slow down decompression and display a great deal if there is a lot of other activity going on in your system. Reasonable. Selects what JPEGView considers to be a reasonable amount of time to give to other applications. Minimal. Selects the minimum amount of time JPEGView can give to other applications. This will slow down any other activity on your system with the benefit of faster decompression and display times when JPEGView is the active application. Use QuickTime to decompress JPEGs (default is on for 680x0 Macintoshes, and off for Power Macintoshes). This option controls whether or not JPEGView uses QuickTimeÕs built-in JPEG decompression to display JPEG images. On 680x0 Macintoshes, QuickTime is a big win if you have it installed, as it is much faster than the Independent JPEG GroupÕs code; however, it is also less forgiving of unusual JPEG images, and occasionally crashes when attempting to decode corrupt data. On Power Macintoshes, the speed difference between the two is minimal, so you might as well use the more robust code. \ No newline at end of file diff --git a/Resources/Help Text/09.File Formats b/Resources/Help Text/09.File Formats new file mode 100644 index 0000000000000000000000000000000000000000..fdb23f83aa31982dc113eec36133cea00beb7a30 GIT binary patch literal 9329 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 document ------+ | | | | | | v v v drawing area ---> image <---- file | | v pixel map At the top of the hierarchy is the application, which serves as the ÒcontainerÓ for all the other objects in JPEGView. Inside the application there can be any number of windows and documents. Be careful not to confuse image objects with document objects, however! A document is some abstract object that is being viewed or edited in the application; an image is what the document contains, i.e., the graphic image inside the document. Window objects in general fall into two categories: those that are displaying a document, and those that are not. Windows that are displaying documents contain exactly one document object (since only one document can appear at a time in a given window) and one drawing area object. Windows that are not displaying a document have no documents and no drawing areas associated with them. Aside from the application object, which can contain many documents and windows, most of JPEGViewÕs objects only contain a single element. That is, windows can only contain one drawing area (if any at all); drawing areas, documents, and files can contain only one image; documents can contain only one file; and images can only contain zero or one pixel map. Although it may have seemed more logical to combine everything into a single object, the current setup fits more smoothly into AppleÕs definitions for the standard AppleEvent suites. The best way to see what commands and objects JPEGView supports is to open its dictionary using the Script Editor. This will produce a list of four suites, or groups, of objects and commands: the Required Suite, the Standard Suite, the QuickDraw Graphics Suite, and the JPEGView Suite. The Required and Standard suites are common to all AppleScript-aware applications, and wonÕt be described here apart from the extensions and limitations imposed by JPEGView. The QuickDraw Graphics Suite provides definitions for pixel maps and drawing areas, two objects used in JPEGView. However, JPEGView only implements a subset of the full definition of these classes, so be careful if youÕve seen them in other applications. Finally, the JPEGView Suite contains two events for reducing images to a particular number of colors and for running the slide show; only the latter event is interesting for scripting purposes. Once youÕve glanced over the classes, try recording some random actions in JPEGView. This will help you get a feel for how JPEGView handles and manipulates objects. Almost everything you do in JPEGView will appear as a script command in the Script EditorÕs window. Finally, note that JPEGView only supports the Òsimple grammarÓ at this time; that is, you can only refer to objects by number or by name. ÒWhoseÓ clauses and conditionals are not supported, although the generic selectors such as every, any, first, last, etc., are supported. Commands in the Required Suite JPEGView supports all four events defined in AppleÕs Required Suite; these are the open, print, quit, and run commands. open: Open the specified object(s). This command is used in JPEGView to open image files. The object it expects is a list of aliases to the files you want to open. If you leave the remaining parameters alone, the image will be opened according to the current preferences settings; however, you can control almost every aspect of the opening procedure through the use of the parameters specified below. Any omitted parameters will take on the values from the preferences settings. on deepest color/deepest grayscale/largest color/largest grayscale/main Ñ allows you to specify which monitor to open the image on using full screen always/always if large/on request if large/never Ñ allows you to specify how JPEGView handles the use of full screen windows expansion true/false Ñ controls whether small images are expanded to maximum size visible true/false Ñ controls whether the image window is initially visible with colors image or reduced or system/reduced or image or system/image or system/reduced or system/system Ñ controls the initial colors used for image drawing, in order of preference; that is, Òimage or reduced or systemÓ means that image colors are preferred, followed by reduced colors, and then standard system colors with quality very high/high/normal Ñ specifies the quality to be used in drawing the opened images bitmaps true/false Ñ controls whether bitmaps are required for the images comments true/false Ñ specifies whether the Comments floating window is automatically displayed for images that have comments type fixing true/false Ñ controls whether file types are automatically fixed changing creators true/false Ñ controls whether creators are changed along with file types no errors true/false Ñ tells JPEGView whether or not it should display error messages; defaults to false Note that since JPEGView only accepts lists of aliases as parameters to the open command, you must manually coerce files or filenames to aliases before passing them to the open command. So, be careful to use Òopen {file as alias}Ó and not just Òopen {file}Ó. print: Print the specified object(s) or file(s). Specifying either files or document objects instructs JPEGView to start printing the appropriate images. quit: Quit application. Quits JPEGView. run: Sent to an application when it is double-clicked. This function performs the startup action specified in the preferences; normally only used by the Finder when it launches JPEGView. Commands in the Standard Suite The Standard Suite provides the basic commands for manipulating objects in JPEGView, and JPEGView supports all of AppleÕs recommended functions in this suite. close: Close an object. In JPEGView, only windows and documents can be closed. Closing a document also closes its corresponding window. The only additional non-standard parameter is: restore colors true/false Ñ controls whether colors are automatically restored after the last image is closed count: Return the number of elements of a particular class within an object. This function is applicable in the standard way to every object in the JPEGView object hierarchy. data size: Return the size in bytes of an object. This function is supported in the standard way for every object and for every property of every object in the JPEGView object hierarchy. delete: Delete an element from an object. This command only works for windows, documents, and pixel maps. For windows and documents, it provides the same functionality as the close command; for pixel maps, it disposes of any offscreen bitmap associated with an image. duplicate: Duplicate object(s). In JPEGView, only documents and windows can be duplicated, and in the case of windows, only windows that contain documents can do it. In addition, the duplicate command supports a visible parameter, whose function is identical to the visible parameter in the open command from the Required Suite. exists: Verify if an object exists. This is supported in the standard way for all objects in the JPEGView object hierarchy. get: Get the data for an object. This function is supported in the standard way for all objects and for all properties of objects in the JPEGView object hierarchy. make: Make a new element. Only windows can be made in JPEGView, and then only static windows, which include the three floating windows, the About box, the Help window, and the Preferences and Slide Show Options dialog. To create a given new window, simply specify its contents property in the with properties parameter. move: Move object(s) to a new location. Both documents and windows can be moved in JPEGView. This allows you to move windows (document windows in the case of documents) in front of or behind other windows in the application. save: Save an object. In JPEGView, only documents and windows containing documents can be saved. In addition to the standard parameters, JPEGView adds the following three optional parameters: preview true/false Ñ specifies whether to create a preview of the document reduced colors true/false Ñ specifies whether to save a reduced color set with the document icons true/false Ñ specifies whether to create custom icons for the document set: Set an objectÕs data. This command works in JPEGView only for data contained in the properties of an object. The data of an actual object cannot be directly set. Objects classes in the Standard Suite application: the JPEGView application. This object sits at the top of the object hierarchy and always exists. It can contain any number of windows and any number of documents. The application properties supported by JPEGView are as follows: clipboard (list of anything) Ñ non-modifiable Ñ since JPEGView does not support copying and pasting, this property always returns an empty list frontmost (boolean) Ñ non-modifiable Ñ this property is true if JPEGView is the frontmost application name (string) Ñ non-modifiable Ñ the name of the application, i.e., ÒJPEGViewÓ version (integer) Ñ non-modifiable Ñ the version number, specified as (major version x 256) + (minor version); for example, version 3.0 is (3 x 256 + 0) = 768 document: a document. This object serves as the container for all images that are manipulated in JPEGView. Documents always contain exactly one file and one image. The supported document properties are: modified (boolean) Ñ non-modifiable Ñ this property is true if the image has been modified; in JPEGView, this property always returns false name (boolean) Ñ modifiable Ñ this is the name of the document selection (boolean) Ñ non-modifiable Ñ this property points to a selection object whose bounds property describes the current selection in this document file: a file. This object specifies information about the file used to store a document. File objects always contain exactly one image in JPEGView. Supported file properties include: stationery (boolean) Ñ non-modifiable Ñ this property is true if the file is a stationery pad document; since JPEGView does not support stantionery pad documents, this will always return false name (boolean) Ñ modifiable Ñ this contains the name of the file, specified as a full pathname; for example, a file named ÒExample.PICTÓ in the folder ÒTemporaryÓ on the volume ÒMy Hard DriveÓ would have a pathname of ÒMy Hard Drive:Temporary:Example.PICTÓ window: a window. Window objects describe properties of the visible (and invisible) windows on the screen. Windows that contain a document will contain exactly one document object and one drawing area object. All other windows will contain no elements. The window properties supported in JPEGView are: bounds (bounding rectangle) Ñ modifiable Ñ this property describes the position and size of the window on the screen; if you want to change the size of a window that contains an image, change the bounds property of the drawing area instead closeable (boolean) Ñ non-modifiable Ñ this property is true if the window has a close box; only the Preferences and Slide Show Options dialogs are missing a close box titled (boolean) Ñ non-modifiable Ñ this property is true if the window has a title bar; this is true of all of JPEGViewÕs windows index (integer) Ñ non-modifiable Ñ this is the position of the window in the list; for instance, the frontmost window would return 1, the second window would return 2, etc. floating (boolean) Ñ non-modifiable Ñ this property is true if the window is a floating window; JPEGViewÕs Statistics, Comments, and Colors windows all qualify as floating modal (boolean) Ñ non-modifiable Ñ this property is true if the window is a modal window; only JPEGViewÕs Preferences and Slide Show Options dialogs are modal resizable (boolean) Ñ non-modifiable Ñ this property is true if the window is resizable; in JPEGView, only image windows are resizable zoomable (boolean) Ñ non-modifiable Ñ this property is true if the window can be zoomed; image windows and the Statistics floating window can be zoomed in JPEGView zoomed (boolean) Ñ modifiable Ñ this property is true if the window is zoomed to a non-standard state name (boolean) Ñ modifiable Ñ this is the title of the window selection (boolean) Ñ non-modifiable Ñ this property points to a selection object whose bounds property describes the current selection in this window visible (boolean) Ñ modifiable Ñ this property is true if the window is currently visible on the desktop full screen (boolean) Ñ modifiable Ñ this property is true if the window is a full-screen window contents (image/full screen image/image statistics/image comments/screen colors/help text/slide show options/preferences/ about box/slide show controls/about help) Ñ non-modifiable Ñ this property describes briefly what the image is displaying Object classes in the QuickDraw Graphics Suite drawing area: a drawing area in a window. This class serves to represent the area of a window inside which images are drawn. In JPEGView, members of the drawing area class always contain exactly one image. The supported properties of the drawing area object include: bounds (bounding rectangle) Ñ modifiable Ñ this property describes the area inside of which the image is drawn; for normal windows, this coincides with the bounds of the window itself; for full-screen windows, this represents the area that the image is drawn in; set this property if you wish to change the size of the displayed image colors (system colors/grayscales/image colors/two pass color reduction) Ñ modifiable Ñ this property specifies the current color set used for drawing the image; if two pass color reduction is requested and the color reduction algorithm has not yet been applied to the image, it will be done immediately color table (color table) Ñ modifiable Ñ this property contains the current full color table of the image; in most cases, it is easier to work with the colors property instead scale (fixed) Ñ modifiable Ñ this property describes the current scaling factor used in drawing the image; set this as an alternative to manipulating the bounds property directly quality (very high/high/normal) Ñ modifiable Ñ this property specifies the current drawing quality applied to the image transfer mode (no dithering/dithering) Ñ modifiable Ñ this property specifies how the image is drawn, either with dithering or without pixel map: a pixel map. This object is used to describe the offscreen buffer that JPEGView uses for fast window updating. The two pixel map properties that are supported are: bounds (bounding rectangle) Ñ non-modifiable Ñ this is the size of the offscreen buffer pixel depth (small integer) Ñ non-modifiable Ñ this is the depth, or number of colors specified as n, where 2^n is the number of colors available Commands in the JPEGView Suite The commands in the JPEGView suite provide access to two of JPEGViewÕs more important features: two-pass color reduction, and slide shows. reduce: Reduce an image to a given number of colors. This command, which applies to image objects only, allows you to calculate an optimal color set reduced to a specified number of colors. The result is a color table object which can be used to set the color table property of a drawing area object. If you want to set an imageÕs colors to the standard reduced color set in JPEGView, set the colors property of the drawing area instead. Normally, this command is not used in scripts. slide show: Set up and begin a JPEGView slide show. This powerful function allows you to specify a folder or a set of files to view in a JPEGView slide show, along with a number of options that control how the images are to be displayed. The options parameters are, naturally, optional, with their values taken from the last set of user preferences if not specified by the command. These options are: with delay seconds Ñ specifies the delay between successive images, in seconds filenames true/false Ñ controls whether filenames are displayed along with each image images from disk true/false Ñ specifies whether the slide show is disk-based or memory-based no errors true/false Ñ specifies whether error messages are suppressed during the slide show importing true/false Ñ controls whether all files found are tried, or whether only files whose file types are correct according to the Finder are opened for display shuffling true/false Ñ controls whether the slides are shuffled before each repetitition of the slide show looping true/false Ñ specifies whether the slide show repeats indefinitely (loops) recursive scan true/false Ñ controls whether a disk-based scan for files scans subfolders recursively user control true/false Ñ specifies whether the slide show is user-controlled or automatic offscreen drawing true/false Ñ controls whether the next slide is prepared offscreen auto comments true/false Ñ controls whether the Comments floating window appears automatically when comments are found in an image hidden windoids true/false Ñ controls whether floating windows (windoids) are automatically hidden at the start of the slide show hidden controls true/false Ñ controls whether the Slide Show Controls floating window is hidden at the start the slide show screen saver true/false Ñ specifies whether to run in screen saver mode; in this mode, JPEGView ensures that it is always the frontmost application, and immediately aborts the slide show and quits whenever the mouse is moved or clicked, or a key is pressed Object classes in the JPEGView Suite image: an image graphic. Image objects in JPEGView describe the fundamental information about the image itself, not about the way in which the image is drawn on your screen. Images can contain zero or one pixel maps, depending on whether the image has an associated offscreen buffer. The properties supported by the image class are: bounds (bounding rectangle) Ñ modifiable Ñ this property specifies the current bounding rectangle of the image; to crop an image, set this property to a rectangle smaller than the originalÊbounds property comments (string) Ñ non-modifiable Ñ this property contains the comments field, if any, found with the image display time (integer) Ñ non-modifiable Ñ this property specifies the amount of time needed to decompress and draw the full image, in milliseconds; it is only set after the image has been decompressed and drawn the first time format (type class) Ñ non-modifiable Ñ this property tells you which format the image is in, according to the file type codes described in the File Formats and File Types chapter, i.e., PICT, JPEG, or GIFf. compression (type class) Ñ non-modifiable Ñ this property specifies a code indicating the type of compression used on the image has image colors (boolean) Ñ non-modifiable Ñ this property is true if the image has its own internally-defined color table has reduced colors (boolean) Ñ non-modifiable Ñ this property is true if the image has a color set produced by two-pass color reduction image colors (color table) Ñ non-modifiable Ñ this property contains the full image color set compressed (boolean) Ñ non-modifiable Ñ this property is true if the image is compressed aborted (boolean) Ñ non-modifiable Ñ this property is true if the last decompression of the image was interrupted in some way banded (boolean) Ñ non-modifiable Ñ this property is true if the full image is actually several smaller horizontal strips connected together corrupt (boolean) Ñ non-modifiable Ñ this property is true if the image data has been found to be invalid in some way cropped (boolean) Ñ non-modifiable Ñ this property is true if the image has been cropped in any way original bounds (bounding rectangle) Ñ non-modifiable Ñ this property contains the full-size original bounds of the image pixel depth (small integer) Ñ non-modifiable Ñ this property specifies the number of colors in the image as n, where 2^n is the total number of colors in the image reduced colors (color table) Ñ non-modifiable Ñ this property contains the full reduced color set length (integer) Ñ non-modifiable Ñ this property contains the length of the image, in bytes The following classes are not really members of the JPEGView object hierarchy; rather, they are really just placeholders for the appropriate file format that you can specify with the save command. picture: an image in PICT format. JFIF: an image in JFIF format. startup screen: an image in Startup Screen format. GIF: an image in GIF format. TIFF: an image in TIFF format. BMP: an image in BMP format. MacPaint: an image in MacPaint format. \ No newline at end of file diff --git a/Resources/Help Text/11.General JPEG Q&A b/Resources/Help Text/11.General JPEG Q&A new file mode 100644 index 0000000..815d450 --- /dev/null +++ b/Resources/Help Text/11.General JPEG Q&A @@ -0,0 +1 @@ +General JPEG Questions and Answers [These questions and answers are taken almost verbatim from the text of the JPEG Frequently Asked Questions list, maintained by Tom Lane. A lot of the information contained here does not pertain very specifically to JPEGView, but rather to the current state of JPEG standards and to the Independent JPEG GroupÕs free software. The latter consists of two general conversion programs: cjpeg, which converts files to JPEG; and djpeg, which converts files from JPEG. (JPEG Convert, a Macintosh version of cjpeg/djpeg, is available from many archive sites.) Note that references to compression quality factors in this section refer to cjpeg and djpeg, which use a scale running from 0 to 100, rather than from 0.00 to 4.00 as does AppleÕs QuickTime. For more information about JPEG in general or the free JPEG software in particular, contact the Independent JPEG Group at jpeg-info@uunet.uu.net.] What is JPEG? JPEG (pronounced Òjay-pegÓ) is a standardized image compression mechanism. JPEG stands for Joint Photographic Experts Group, the original name of the committee that wrote the standard. JPEG is designed for compressing either full-color or gray-scale images of natural, real-world scenes. It works well on photographs, naturalistic artwork, and similar material; not so well on lettering, simple cartoons, or line drawings. JPEG handles only still images, but there is a related standard called MPEG for motion pictures. JPEG is Òlossy,Ó meaning that the decompressed image isnÕt quite the same as the one you started with. (There are lossless image compression algorithms, but JPEG achieves much greater compression than is possible with lossless methods.) JPEG is designed to exploit known limitations of the human eye, notably the fact that small color details arenÕt perceived as well as small details of light-and-dark. Thus, JPEG is intended for compressing images that will be looked at by humans. If you plan to machine-analyze your images, the small errors introduced by JPEG may be a problem for you, even if they are invisible to the eye. A useful property of JPEG is that the degree of lossiness can be varied by adjusting compression parameters. This means that the image maker can trade off file size against output image quality. You can make extremely small files if you donÕt mind poor quality; this is useful for applications like indexing image archives. Conversely, if you arenÕt happy with the output quality at the default compression setting, you can jack up the quality until you are satisfied, and accept lesser compression. Why use JPEG? There are two good reasons: to make your image files smaller, and to store 24-bit-per-pixel color data instead of 8-bit-per-pixel data. Making image files smaller is a big win for transmitting files across networks and for archiving libraries of images. Being able to compress a 2 Mbyte full-color file down to 100 Kbytes or so makes a big difference in disk space and transmission time! If your viewing software doesnÕt support JPEG directly, youÕll have to convert JPEG to some other format for viewing or manipulating images. Even with a JPEG-capable viewer, it takes longer to decode and view a JPEG image than to view an image of a simpler format such as GIF. Thus, using JPEG is essentially a time/space tradeoff: you give up some time in order to store or transmit an image more cheaply. ItÕs worth noting that when network or phone transmission is involved, the time savings from transferring a shorter file can be greater than the extra time needed to decompress the file. The second fundamental advantage of JPEG is that it stores full color information: 24 bits/pixel (16 million colors). GIF, the other image format widely used on the networks, can only store 8 bits/pixel (256 or fewer colors). GIF is reasonably well matched to inexpensive computer displays Ñ most run-of-the-mill PCs canÕt display more than 256 distinct colors at once. But full-color hardware is getting cheaper all the time, and JPEG images look much better than GIFs on such hardware. Within a couple of years, 8-bit GIF will seem as obsolete as black-and-white MacPaint format does today. Furthermore, for reasons detailed below, JPEG is far more useful than GIF for exchanging images among people with widely varying display hardware. Hence JPEG is considerably more appropriate than GIF for use as an image exchange standard. A lot of people are scared off by the term Òlossy compressionÓ. But when it comes to representing real-world scenes, no digital image format can retain all the information that impinges on your eyeball. In comparison with the real-world scene, JPEG loses far less information than GIF. The technical meaning of ÒlossyÓ has nothing to do with this, though; it refers to loss of information over repeated compression cycles, a problem that you may or may not care about. (If you do, see below.) When should I use JPEG, and when should I stick with GIF? JPEG is not going to displace GIF entirely; for some types of images, GIF is superior in image quality, file size, or both. One of the first things to learn about JPEG is which kinds of images to apply it to. Generally speaking, JPEG is superior to GIF for storing full-color or gray-scale images of ÒrealisticÓ scenes; that means scanned photographs and similar material. Any continuous variation in color, such as occurs in highlighted or shaded areas, will be represented more faithfully and in less space by JPEG than by GIF. GIF does significantly better on images with only a few distinct colors, such as line drawings and simple cartoons. Not only is GIF lossless for such images, but it often compresses them more than JPEG can. For example, large areas of pixels that are all exactly the same color are compressed very efficiently indeed by GIF. JPEG canÕt squeeze such data as much as GIF does without introducing visible defects. (One implication of this is that large single-color borders are quite cheap in GIF files, while they are best avoided in JPEG files.) Computer-drawn images (ray-traced scenes, for instance) usually fall between photographs and cartoons in terms of complexity. The more complex and subtly rendered the image, the more likely that JPEG will do well on it. The same goes for semi-realistic artwork (fantasy drawings and such). JPEG has a hard time with very sharp edges: a row of pure-black pixels adjacent to a row of pure-white pixels, for example. Sharp edges tend to come out blurred unless you use a very high quality setting. Edges this sharp are rare in scanned photographs, but are fairly common in GIF files: borders, overlaid text, etc. The blurriness is particularly objectionable with text thatÕs only a few pixels high. If you have a GIF with a lot of small-size overlaid text, donÕt JPEG it. Plain black-and-white (two level) images should never be converted to JPEG; they violate all of the conditions given above. You need at least about 16 gray levels before JPEG is useful for gray-scale images. It should also be noted that GIF is lossless for gray-scale images of up to 256 levels, while JPEG is not. If you have a large library of GIF images, you may want to save space by converting the GIFs to JPEG. This is trickier than it may seem Ñ even when the GIFs contain photographic images, they are actually very poor source material for JPEG, because the images have been color-reduced. Non-photographic images should generally be left in GIF form. Good-quality photographic GIFs can often be converted with no visible quality loss, but only if you know what you are doing and you take the time to work on each image individually. Otherwise youÕre likely to lose a lot of image quality or waste a lot of disk spaceÉquite possibly both. ThereÕs more information below about GIF to JPEG conversion. How well does JPEG compress images? Very well indeed, when working with its intended type of image (photographs and suchlike). For full-color images, the uncompressed data is normally 24 bits/pixel. The best known lossless compression methods can compress such data about 2:1 on average. JPEG can typically achieve 10:1 to 20:1 compression without visible loss, bringing the effective storage requirement down to 1 to 2 bits/pixel. 30:1 to 50:1 compression is possible with small to moderate defects, while for very-low-quality purposes such as previews or archive indexes, 100:1 compression is quite feasible. An image compressed 100:1 with JPEG takes up the same space as a full-color one-tenth-scale thumbnail image, but it retains much more detail than such a thumbnail. Gray-scale images do not compress by such large factors. Because the human eye is much more sensitive to brightness variations than to hue variations, JPEG can compress hue data more heavily than brightness (gray-scale) data. A gray-scale JPEG file is generally only about 10%-25% smaller than a full-color JPEG file of similar visual quality. But the uncompressed gray-scale data is only 8 bits/pixel, or one-third the size of the color data, so the calculated compression ratio is much lower. The threshold of visible loss is often around 5:1 compression for gray-scale images. The exact threshold at which errors become visible depends on your viewing conditions. The smaller an individual pixel, the harder it is to see an error; so errors are more visible on a computer screen (at maybe 70 dots/inch) than on a high-quality color printout (300 or more dots/inch). Thus a higher-resolution image can tolerate more compressionÉwhich is fortunate considering itÕs much bigger to start with. The numbers quoted above are typical for screen viewing. Also note that the threshold of visible error varies somewhat across images. WhatÕs all this hoopla about color quantization? Most people donÕt have full-color (24 bit per pixel) display hardware. Typical display hardware stores 8 or fewer bits per pixel, so it can display 256 or fewer distinct colors at a time. To display a full-color image, the computer must choose an appropriate set of representative colors and map the image into these colors. This process is called Òcolor quantizationÓ. (This is something of a misnomer; Òcolor selectionÓ or Òcolor reductionÓ would be a better term. JPEGView calls it Òcolor reductionÓ.) Clearly, color quantization is a lossy process. It turns out that for most images, the details of the color quantization algorithm have much more impact on the final image quality than do any errors introduced by JPEG itself (except at the very lowest JPEG quality settings). Making a good color quantization algorithm is a black art, and no single algorithm is best for all images. Since JPEG is a full-color format, converting a color JPEG image for display on 8-bit-or-less hardware requires color quantization. The speed and image quality of a JPEG viewer running on such hardware are largely determined by its quantization algorithm. YouÕll see great variation in image quality among viewers on 8-bit displays, much more than occurs on 24-bit displays. On the other hand, a GIF image has already been quantized to 256 or fewer colors. (A GIF does have a specific number of colors in its palette, and the format doesnÕt allow more than 256 palette entries.) GIF has the advantage that the image maker precomputes the color quantization, so viewers donÕt have to; this is one of the things that make GIF viewers faster than JPEG viewers. But this is also the disadvantage of GIF: youÕre stuck with the makerÕs quantization. If the maker quantized to a different number of colors than what you can display, youÕll either waste display capability or have to quantize again to further reduce the number of colors (which results in much poorer image quality than if you had quantized once from a full-color image). Furthermore, if the maker didnÕt use a high-quality color quantization algorithm, youÕre out of luck Ñ the image is ruined. For this reason, JPEG promises significantly better image quality than GIF for all users whose machines donÕt match the image makerÕs display hardware. JPEGÕs full color image can be quantized to precisely match the viewerÕs display hardware. Furthermore, you will be able to take advantage of future improvements in quantization algorithms (there is a lot of active research in this area), or purchase better display hardware, to get a better view of JPEG images you already have. With a GIF, youÕre stuck forevermore with what was sent. A growing number of people have better-than-8-bit display hardware already: 15-bit Òhi-colorÓ PC displays, true 24-bit displays on workstations and Macintoshes, etc. For these people, GIF is already obsolete, as it cannot represent an image to the full capabilities of their display. JPEG images can drive these displays much more effectively. In short, JPEG is an all-around better choice than GIF for representing images in a machine-independent fashion. What are some rules of thumb for converting GIF images to JPEG? Converting GIF files to JPEG is a tricky business Ñ you are piling one set of limitations atop a quite different set, and the results can be awful. Certainly a JPEG made from a GIF will never be as good as a JPEG made from true 24-bit color data. But if what youÕve got is GIFs, and you need to save space, here are some hints for getting the best results. With care and a clean source image, itÕs often possible to make a JPEG of quality equivalent to the GIF. This does not mean that the JPEG looks identical to the GIF Ñ it probably wonÕt on an 8-bit display, because the color quantization process used to display the JPEG wonÕt exactly match the GIFÕs quantization. (See previous item for more about that.) But given a good viewer, the JPEG will look as good as the GIF. Some people claim that on 24-bit displays, a carefully converted JPEG can look better than the GIF source, because dither patterns have been eliminated. (More about dithering in a moment.) On the other hand, JPEG conversion will degrade an unsuitable image or one that is converted carelessly. If you are not willing to take the amount of trouble suggested below, youÕre much better off leaving your GIF images alone. Simply cranking the JPEG quality setting up to a very high value wastes space (which defeats the whole point of the exerciseÉ) and some images will be degraded anyway. The first rule is never to convert an image thatÕs not appropriate for JPEG. Large, high-visual-quality photographic images are usually the best material. And they take up lots of space in GIF form, so they offer significant potential space savings. (A good rule of thumb is not to bother converting any GIF thatÕs much under 100 Kbytes; the potential space savings isnÕt worth the hassle.) The second rule is to look at each JPEG, to make sure you are happy with it, before throwing away the corresponding GIF; this will give you a chance to re-do the conversion with a higher quality setting if necessary. Also compare the file sizes Ñ if the image isnÕt suitable JPEG material, a JPEG file of reasonable quality may come out larger than the GIF. The third rule is to get rid of the border. Many people have developed an odd habit of putting a large single-color border around a GIF image. While useless, this is nearly free in terms of storage cost in GIF files. It is not free in JPEG files, either in storage space or in decoding time; and the sharp border boundary can create visible artifacts (ÒghostÓ edges). Furthermore, when viewing a bordered JPEG on an 8-bit display, the quantizer will think the border color is important because thereÕs so much of it, and hence will waste color palette entries on the border, thus actually reducing the displayed quality of the main part of the image! So do yourself a favor and crop off any border before JPEGing. Gray-scale images usually convert without much problem. When using cjpeg, be sure to specify -gray. (By default, cjpeg treats GIFs as color files; this works but wastes space and time for gray-scale data.) Quality settings around the default (75) are usually fine. Color images are much trickier. Color GIFs of photographic images are usually ÒditheredÓ to fool your eye into seeing more than the 256 colors that GIF can actually store. If you enlarge the image, you will find that adjacent pixels are often of significantly different colors; at normal size the eye averages these pixels together to produce the illusion of an intermediate color value. The trouble with dithering is that, to JPEG, it looks like high-spatial-frequency color noise; and JPEG canÕt compress noise very well. The resulting JPEG file is both larger and of lower image quality than what you would have gotten from JPEGing the original full color image (if you had it). To get around this, you need to ÒsmoothÓ the GIF image before compression. Smoothing averages together nearby pixels, thus approximating the color that you thought you saw anyway, and in the process getting rid of the rapid color changes that give JPEG trouble. Proper use of smoothing will both reduce the size of the compressed file and give you a better-looking output image than youÕd get without smoothing. With the free JPEG software (or programs based on it), a simple smoothing capability is built in. Try Ò-smooth 10Ó or so when converting GIFs. Values of 10 to 25 seem to work well for high-quality GIFs. Heavy-handed dithering may require larger smoothing factors. (If you can see regular fine-scale patterns on the GIF image even without enlargement, then strong smoothing is definitely called for.) Too large a smoothing factor will blur the output image, which you donÕt want. If you are an image processing wizard, you can also do smoothing with a separate filtering program, but appropriate use of such tools is beyond the scope of this article. Quality settings around 85 (a bit higher than default) usually work well when converting color GIFs, assuming that youÕve picked a good smoothing factor. You may need to go higher if you canÕt hide the dithering pattern with a reasonable smoothing factor. Really badly dithered GIFs are best left as GIFs. DonÕt expect JPEG files converted from GIFs to be as small as those created directly from full-color originals. You wonÕt be able to smooth away all of the dithering noise without ruining the image, and this noise wastes space. Typically, a good-quality converted JPEG will be 1/2 to 1/3rd the size of the GIF file, not 1/4th as suggested above. (If the JPEG comes out much more than half the size of the GIF, this is a good sign that the image shouldnÕt be converted at all.) The upshot of all this is that Òcjpeg -quality 85 -smooth 10Ó is probably a good starting point for converting color GIFs. But if you care about the image, youÕll want to check the results and maybe try a few other settings. Blindly converting a large GIF library at this or any other setting is a recipe for disaster. Does loss accumulate with repeated compression/ decompression? It would be nice if, having compressed an image with JPEG, you could decompress it, manipulate it (crop off a border, say), and recompress it without any further image degradation beyond what you lost initially. Unfortunately this is not the case. In general, recompressing an altered image loses more information. Hence itÕs important to minimize the number of generations of JPEG compression between initial and final versions of an image. It turns out that if you decompress and recompress an image at the same quality setting first used, little or no further degradation occurs. (Counterintuitively, this works better the lower the quality setting. But you must use exactly the same setting, or all bets are off.) This means that you can make local modifications to an image without material degradation of other areas of the image. Unfortunately, cropping doesnÕt count as a local change! JPEG processes the image in small blocks, and cropping usually moves the block boundaries, so that the image looks completely different to JPEG. You can take advantage of the low-degradation behavior if you are careful to crop the top and left margins only by a multiple of the block size (typically 16 pixels), so that the remaining blocks start in the same places. The bottom line is that JPEG is a useful format for archival storage and transmission of images, but you donÕt want to use it as an intermediate format for sequences of image manipulation steps. Use a lossless format (uncompressed PICT, TIFF, etc) while working on the image, then JPEG it when you are ready to file it away. Aside from avoiding degradation, you will save a lot of compression/decompression time this wayÉ Why all the argument about file formats? Strictly speaking, JPEG refers only to a family of compression algorithms; it does not refer to a specific image file format. The JPEG committee was prevented from defining a file format by turf wars within the international standards organizations. Since we canÕt actually exchange images with anyone else unless we agree on a common file format, this leaves us with a problem. In the absence of official standards, a number of JPEG program writers have just gone off to Òdo their own thingÓ, and as a result their programs arenÕt compatible with anybody elseÕs. The closest thing we have to a standard JPEG format is some work thatÕs been coordinated by people at C-Cube Microsystems. They have defined two JPEG-based file formats: ¥ JFIF (JPEG File Interchange Format), a Òlow-endÓ format that transports pixels and not much else. ¥ TIFF/JPEG, aka TIFF 6.0, an extension of the Aldus TIFF format. TIFF is a Òhigh-endÓ format that will let you record just about everything you ever wanted to know about an image, and a lot more besides. TIFF is a lot more complex than JFIF, and is generally less transportable, because different vendors have often implemented slightly different and incompatible subsets of TIFF. Both of these formats were developed with input from all the major vendors of JPEG-related products; itÕs reasonably likely that future commercial products will adhere to one or both standards. JFIF has emerged as the de-facto standard. JFIF is simpler than TIFF and is available now; the TIFF 6.0 spec has only recently been officially adopted, and it is still unusably vague on some crucial details. Even when TIFF/JPEG is well defined, the JFIF format is likely to be a widely supported lowest common denominator; TIFF/JPEG files may never be as transportable. In the Macintosh world, all images are supposed to appear in AppleÕs standard PICT format. QuickTimeÕs JPEG compressor actually produces a JFIF-compatible data sequence with a PICT ÒwrapperÓ around it. Conversion between PICT/JPEG and JFIF is thus a fairly simple matter of adding or removing the ÒwrapperÓ. JPEGView and several other Macintosh programs can do this for you. But non-Macintosh computers donÕt know anything about PICT, so be sure to convert a PICT/JPEG file to JFIF format before giving it to anyone who uses a non-Macintosh computer. Just to muddy the waters, there are a couple of proprietary JPEG-based file formats to worry about. One that you are likely to find on some BBS systems is Handmade Software, Inc.Õs ÒHSIÓ format. ThereÕs no way to read HSI files except by using HSIÕs software Ñ which runs only on PCs. About all you can do is try to persuade the BBS operator to convert to the standardized, public-domain JFIF format. IsnÕt there a lossless JPEG? ThereÕs a great deal of confusion on this subject. The JPEG committee did define a truly lossless compression algorithm (i.e., one that guarantees the final output is bit-for-bit identical to the original input). However, this lossless mode has almost nothing in common with the regular lossy JPEG algorithm, and it offers much less compression. At present, very few implementations of lossless JPEG exist. Lossless JPEG typically compresses full-color data by around 2:1. Lossless JPEG works well only on continuous-tone images; it does not provide useful compression of palette-color images or low-bit-depth images. (The JBIG standard is considered superior to lossless JPEG for images of less than 6 bits/sample.) Cranking a regular JPEG implementation up to its maximum quality setting does not get you a lossless image. Even at the maximum possible quality setting, regular JPEG is not lossless, because it is subject to roundoff errors in various calculations. Roundoff errors are nearly always too small to be seen, but they will accumulate if you put the image through multiple cycles of compression. Many implementations wonÕt even let you get to the maximum possible setting, because itÕs such an inefficient way to use regular JPEG. With the IJG JPEG software, for example, you have to say not only Ò-quality 100Ó but also Ò-sample 1x1Ó to eliminate all deliberate loss of information. The resulting files are far larger and of only fractionally better quality than files generated at more reasonable settings. If you really need lossless storage, donÕt try to approximate it with regular JPEG. \ No newline at end of file diff --git a/Resources/Help Text/12.JPEGView Q&A b/Resources/Help Text/12.JPEGView Q&A new file mode 100644 index 0000000..e45602a --- /dev/null +++ b/Resources/Help Text/12.JPEGView Q&A @@ -0,0 +1 @@ +JPEGView Questions and Answers Why canÕt my friends read the JPEG files I give them? The problem with transferring JPEG files from the Macintosh to another system is twofold. First, most Macintosh JPEG files are stored as QuickTime PICTs, rather than as standard JFIF files. So, if youÕre running into difficulties, first make sure you use JPEGView to save any JPEG image as a JFIF image. The second problem has to do with file transfers; if you save custom icons or custom color sets with your JFIF image, it creates resources in the JFIF file that might cause problems when transferring those files. To be absolutely safe, make sure that you turn off custom icons and custom color sets before saving your JFIF file (previews are still okay, however). Why doesnÕt the JPEGView JFIF Preview icon show up when I start my system? The JPEGView JFIF Preview extension isnÕt really a standard extension, in that it doesnÕt execute any code at startup. Rather, it is a QuickTime component, which means that QuickTime looks for it in the Extensions folder, and automatically loads and uses it whenever it needs to view a JFIF preview. Since it doesnÕt execute anything at startup, the extension doesnÕt display an icon at the bottom of your screen. However, it is still working to provide access to JFIF previews. Why doesnÕt JPEGView have scroll bars? JPEGView doesnÕt use scroll bars for two very good reasons: first, with scroll bars you have to have enough memory to buffer the entire decompressed image at full resolution, which makes the memory requirements phenomenally high for 24-bit JPEG images; and second, JPEGView implements a Crop & Zoom feature which provides the same functionality as scroll bars but with several important advantages. The section in the Hints and Tips chapter entitled ÒMake good use of the Crop & Zoom featureÓ explains these advantages in more detail. Why does JPEGView crash when loading corrupted JPEG images? This problem with terrible crashes was a result of loose error checking in the QuickTime 1.0 JPEG decoder. This is not Ñ I repeat Ñ not my fault! The solution is quite simply to upgrade to the latest version of QuickTime (version 1.6.1 as of December 1993), which is far more robust in handling damaged JPEGs. And yes, there are some images out there that are bound to crash the new version on occasion. NobodyÕs perfect! Where can I get the latest version of QuickTime? AppleÕs plan for QuickTime seems to include making it as widely available as possible. If you have ftp access, just ftp to ftp.apple.com, login as ÒanonymousÓ, and give your email address as a password. The latest version should be in the /dts/mac/sys.soft/quicktime directory. Otherwise, you may want to check with your local Apple dealer (bring a blank floppy with you), who might be willing to copy it for you. Also, check your local BBS systems. Where can I get a copy of AppleScript? Unlike QuickTime, AppleScript does not come absolutely free. At present, the only two viable avenues for obtaining AppleScript are by ordering it from APDA, in which case it will cost you $20 plus tax and shipping, or by picking up the very recent and very well-written The Tao of AppleScript, written by Derrick Schneider and published by Hayden Books. This latter option is probably the best for those just getting started with AppleScript, as it includes not only a good introduction to the AppleScript commands and functionality, but also a copy of the AppleScript extension and some scripting software for $25. Why canÕt JPEGView convert between formats other than JFIF and QuickTime? Why canÕt JPEGView create new images? Why canÕt JPEGView map my image onto a complex three-dimensional object? JPEGView is called JPEGView for a very good reason: it was written as an image viewer, not as an image conversion package. Its ability to convert between JFIF and QuickTime PICT format is simply there as a convenient means of adding/removing the QuickTime PICT header; no additional compression or decompression of the image is involved. Its features in the Save dialog Ñ saving cropped PICTs and saving reduced color sets Ñ are all there for the purpose of improving the on-screen viewing of JPEG images. And its ability to add previews and icons to images is implemented to allow you to see in advance what you will be viewing on your screen. One of the primary reasons for adding GIF support was to lessen the need to convert all GIF files to JPEGs. All of this adds up to sharpen the focus of JPEGView as an application; I think youÕll find that its special features, low memory requirements, and overall stability are a direct result of keeping its feature set under control. Why are my windows filled with strange patterns of dots? Because JPEGView has marked that window for slow updating, meaning that the image is going to need to be decompressed again before it can be displayed. See the section on ÒFast and Slow Window UpdatesÓ in the Viewing Images chapter for a precise description of whatÕs going on. Why donÕt some of my JPEGView documents have icons? If you upgraded from a previous version of JPEGView, which did not handle some of the more recent types of image files, then the Finder doesnÕt realize that the new version supports them. To solve this, simply rebuild your desktop by holding down the Command () and Option keys during startup. Why does JPEGView run out of memory during a slide show? When JPEGView runs a slide show, it needs to have enough memory to hold two compressed images in memory simultaneously, in addition to any memory needed for color reduction and for the JPEGView code itself. The reason for this is that while the current slide is displayed, JPEGView will prepare the next image for display, in order to help minimize the delay between slides. Thus, to ensure that you have enough memory to run your slide show, make sure you give JPEGView enough memory to hold the two largest compressed images in memory, plus about 500k of overhead. Why are the progress percentages so erratic with PICT images? This is one of QuickTimeÕs ÒfeaturesÓ: you tell it what subroutine to call for progress updates, and itÕs supposed to call it regularly. Unfortunately, this doesnÕt always happen as regularly as IÕd like, but thereÕs nothing I can do to fix it. CÕest la vie. QuickTime 1.0 is particularly notorious for this problem; QuickTime 1.5 and later shows a marked improvement, but things could still be better. What is banding? Banding is a technique used by AppleÕs QuickTime to allow you to compress large JPEG images in a small amount of memory. Essentially, it involves dividing the image vertically into several strips, or Òbands,Ó and compressing them separately. Unfortunately, this also makes them rather difficult to reassemble, except in the context of the QuickTime PICT format. For this reason, banded images cannot be converted to JFIF files. Where can I get JPEG pictures? On the Internet, you can now find JPEG pictures via anonymous FTP at the Washington University archives (wuarchive.wustl.edu). Simply log in as ÒanonymousÓ, give your email address as a password, and begin poking around. Additionally, those with Usenet access should check out the alt.binaries.pictures newsgroups, which are becoming more and more dominated by full-color JPEG images every day. Where can I get GIF pictures? If youÕre on the Internet, youÕre in luck: check out the GIF archives of wuarchive.wustl.edu via anonymous FTP (give your email address as the password). There are also quite a lot of BBS systems that carry GIF files. Look around and youÕre bound to find some! \ No newline at end of file diff --git a/Resources/Help Text/13.Hints And Tips b/Resources/Help Text/13.Hints And Tips new file mode 100644 index 0000000..8386a13 --- /dev/null +++ b/Resources/Help Text/13.Hints And Tips @@ -0,0 +1 @@ +Hints and Tips Here are some useful techniques you can use to get the most out of JPEGView. You can sacrifice quality and system response time for speed. There are several techniques you can use to make JPEGView open and display images more quickly; however, as with all things, there are tradeoffs involved. If you donÕt mind sacrificing a little bit of picture quality, you can gain a great deal of speed. First, if youÕre working on a color system, set the default display quality to Normal (under the Drawing preferences); although JPEGViewÕs new dithering routines give superior quality, they are somewhat slower than the built-in routines that Apple provides. Returning to normal quality will make scaling and dithering of images go faster. If you are on a 256-color system, you can also gain a lot of speed by turning off two-pass color reduction (choose ÒNeverÓ under the ÒAutomatically reduce images to 16 or 256 colorsÓ options in the Drawing preferences). Your images will look much grainier, but they only need to be decompressed once to be displayed. Alternatively, if you donÕt mind working in grayscales, you can open the Monitors controls panel, and select ÒGrayscalesÓ. JPEGView never does two-pass color reduction when displaying images on a grayscale device, and you get excellent quality with 256 grays. Finally, if you donÕt mind slowing other applications down to a halt, you can set the ÒTime given to other applicationsÓ option to ÒMinimalÓ (under the Miscellany preferences). This causes JPEGView to hog more of the processor time for drawing, making it work faster overall. If you have memory, use it! Increase JPEGViewÕs memory as much as you can afford to (using the Get Info box from the Finder). JPEGView comes initially set to use only 1024K of memory; although this is adequate for most basic operations, there is a great advantage to be gained by increasing the available memory. When JPEGView has enough free memory, it will store an off-screen copy of the uncompressed image displayed on your screen, which will be used to redraw obscured parts of the window instantaneously. If there is not enough free memory for this extra copy, JPEGView will have to decompress the image again before it can update an obscured window. In addition, if you use two-pass color reduction and give JPEGView enough memory for a 24-bit image the size of your screen, the image will only need to be decompressed once. To give you an idea of how much memory is needed for optimal performance, here is a table of minimum recommended memory sizes for various monitor setups. To determine how much memory you should give to JPEGView, take the value in the table appropriate for your monitor and add to that the compressed size of the largest image you would like to view. For 256 colors with no color reduction: ¥ 12Ó monitors: 500K ¥ 13Ó monitors: 600K ¥ 16Ó/full-page monitors: 850K ¥ 21Ó/two-page monitors: 1300K For 256 colors with color reduction, or for Millions of colors: ¥ 12Ó monitors: 1100K ¥ 13Ó monitors: 1600K ¥ 16Ó/full-page monitors: 2500K ¥ 21Ó/two-page monitors: 4300K Note again that these memory values are not hard minimums; rather, they are the minimum memory needed to show optimum performance on single images. The default allocation of 1024K is adequate for viewing almost any image less than 500K compressed, albeit with some speed degradation. Also, note that if you have virtual memory, you should never give JPEGView more memory than the amount of real, physical RAM you have in your system. Otherwise, your hard drive is going to go nuts while JPEGView tries to access more memory than you have! Make good use of the Crop & Zoom feature in the View menu. There is a lot of power hidden in this innocuously titled feature! In fact, the primary reason for it being there, believe it or not, is that it is a replacement for scroll bars. With most image viewing utilities on the Macintosh, you are initially shown only a portion of the image, which you then must scroll around in, looking for whatever details youÕre interested in. If youÕre lucky, maybe it will let you automatically scale the image to fit on your screen. JPEGView takes exactly the opposite approach: you are given the full image first, scaled to fit on your screen, with the option of zooming in on any part of that image. To do this, you simply click and drag a selection rectangle on your image, and then select Crop & Zoom from the Edit menu. Additionally, when used in conjunction with the Select Screen Area option in the Edit menu, you can automatically select a screen-sized chunk of the image to view at full resolution by simply dragging the selection rectangle anywhere in your image. This approach has three important advantages: first, you gain back all the screen area taken up by those annoying scroll bars in the window; second, you are not required to have enough memory to buffer the entire decompressed image at full resolution; and finally, rather than scrolling around helplessly wondering what you are looking for, you can see with your own eyes the full image and move the selection rectangle over the interesting portions. It may not be the method youÕre used to, but I believe it is far more powerful than the standard scroll bars. Create a folder of aliases to use for your slide show. This technique allows you to choose exactly which images you want to display in your slide show without having to reshuffle your image collection. Simply make aliases of all the images you want to have in your slide show, drag them all into a separate folder, and run the slide show from that folder. JPEGView will automatically resolve the aliases and display the images as you would expect. Make sure you convert JPEGs to JFIF format before posting and trading them! When swapping JPEG pictures with others Ñ and especially when uploading JPEGs to public access sites! Ñ always make sure you save the image as a JFIF file; otherwise, only Macintosh users will be able to read the file and youÕre liable to make some others upset! You should also save JFIF images without custom icons and reduced color information Ñ this extra information tends to confuse some file transfer utilities! Be careful if you are converting your GIFs to JPEGs! A heated and never-ending debate has been filling the Usenet over whether converting GIF files to JPEGs is a good idea. Those opposed to the idea claim that JPEG was not designed to work with 256 (or fewer) color pictures and that JPEG only makes bad pictures look worse. Proponents feel that the space savings gained more than makes up for any quality degradation, which becomes minimal for high-quality GIFs. So, whoÕs right and whoÕs wrong? Unfortunately, it depends on the GIF image. For line drawings, cartoons, and GIFs with very few colors (16 or less), conversion to JPEG is usually a bad idea, as GIF compresses such images very well and JPEG will likely create some unwanted ÒnoiseÓ in the image. For high-quality, 256-color GIF images, JPEG compression does pretty well and introduces little visible loss in image quality. For other images, a judgement can only be made on an image-by-image basis. The conversion issue is by no means clear-cut. \ No newline at end of file diff --git a/Resources/Help Text/14.Contacting the Author b/Resources/Help Text/14.Contacting the Author new file mode 100644 index 0000000..6d4cf9b --- /dev/null +++ b/Resources/Help Text/14.Contacting the Author @@ -0,0 +1 @@ +Contacting the Author JPEGView is postcardware, meaning that if you find yourself using JPEGView regularly, I am asking you to send me a postcard. So donÕt be shy, just scribble your name, address, an email address if you have one, and any comments you wish (or none, if you prefer) on a postcard and slip it in your local mailbox addressed to me at: Aaron Giles 182 E. 95th Street 11E New York, NY 10128 U.S.A. What do you get for your postcard? Well, if you give me an email address that I can access through the Internet, I plan on providing updates and information through a mailing list IÕve set up. You will likely receive information about new versions before everyone else. Also, postcards provide encouragement; if I know many people are using JPEGView and find it useful, I have far more incentive to improve it in the future. SoÉ if youÕd like to see an even more powerful image viewer in the future, a postcard would certainly help! Any user of JPEGView 3.0 or later also has the option of becoming a fully registered user. Registered users who send in a one-time registration fee of US$20 receive a printed, bound copy of the full JPEGView documentation, along with an official JPEGView 3.2 release disk, containing the complete JPEGView 3.2 release plus a few of my favorite JPEG images. My current U.S. Mail address can be found in the chapter Contacting the Author, later on in this documentation. Overseas users who wish to avoid the hassle and fees of international money orders are asked to simply send the equivalent of US$20 in cash, plus about US$3 extra for postage (everything is sent airmail). Although this is not recommended by the post office, you can usually get away with it as long as you do well to mask the fact that there is cash enclosed, i.e., make sure it is wrapped in sufficiently opaque paper. Note that registration is optional; the only ÒpaymentÓ that is required for individual use of JPEGView is a postcard. Finally, a very simple unlimited site license is available for universities and companies that wish to make JPEGView 3.3 an officially supported product Ñ and it typically only costs you the low low price of a few individual registrations (US$50 to be exact)! Contact me via email (giles@med.cornell.edu) or U.S. Mail (at the address above) for full details, or just go ahead and send in the cash (most people seem to do it anyway!) Purchase orders are welcome. Organizations and individuals who are interested in distributing JPEGView with their products should contact me first before doing so. IÕm usually pretty flexible about licensing, especially for Ògood causesÓ, so if youÕre interested, please donÕt hesitate to get in touch with me about it! I would also love to hear any comments, suggestions, bug reports, etc., from anyone using JPEGView. To get them to me, you can either include them with your postcard (preferred), or, if youÕve already sent your postcard, you can send them to me via email on the Internet at: giles@med.cornell.edu or through email on America On-Line, using the address: AGiles If you send me bug reports that appear to be QuickTime-related, I will forward them to the QuickTime engineers at Apple. \ No newline at end of file diff --git a/Resources/Help Text/15.Acknowledgements b/Resources/Help Text/15.Acknowledgements new file mode 100644 index 0000000..c82cdd7 --- /dev/null +++ b/Resources/Help Text/15.Acknowledgements @@ -0,0 +1 @@ +Acknowledgments JPEGView was Ñ for the most part Ñ written, conceived, produced, and documented by Aaron Giles. Behind the scenes, however, were quite a number of other rather important people you should know about. Dirty Work First I want to thank all those other programmers who were nice enough to do some of the dirty work for me. Their efforts in particular are responsible for making JPEGView work so smoothly: Troy Gaul wrote Infinity Windoid, the code that draws the way cool floating windows everyone likes so much. Ramon Felciano wrote Mercutio, the code which draws the menus and handles lots of weird keypresses. The Independent JPEG Group, headed by Tom Lane, wrote the original color reduction algorithm, which was used as the basis for JPEGViewÕs color reduction, in addition to the JPEG decompression code which is used as an alternative to QuickTime. Ross Williams wrote LZRW1, the data compression technique used to squeeze the on-line help down to a reasonable size. Prerelease Hell A big part of putting together a new release of JPEGView is the serious amount of testing that is needed to make sure everything works on all (most?) machines. To this end, I would like to acknowledge all the alpha and beta testers who have contributed toward testing this JPEGView release: Bob Andrews, Jim Brunner, Justin Collins, Shawn Connelly, John Coolidge, Ramon Felciano, Mike Fetzer, Troy Gaul, Stephen Haase, Paul Jacoby, Paul Jensen, Dave Johnson, Hugh Johnson, David Johnston, Mark Krueger, Tom Lane, Richard Lim, Tim Lowe, Robert Mah, Tom McDougal, Sam Neal, Tim North, Victor Norton, Brian Olson, Dan Pendergrass, Steve Poole, Charlie Reiman, Axel M. Roest, Eric Sack, Francois Schiettecatte, Bart Sears, James N. Stricherz, Steve Unger, Chris Webster. Friends in High Places A few special words of thanks are in order for several Apple employees who have made all the difference in helping me make JPEGView a success. Mark Krueger was the guy who originally noticed JPEGView and helped me change it from a really basic hack into a robust QuickTime application. Tim Lowe has been instrumental in helping me adopt and adapt to new Apple technologies Ñ especially AppleScript Ñ faster than I would have ever been able to without him. And finally, thanks to Jim Pelkey and Linda Haas, for organizing the PowerPC developerÕs kitchen, and for making it such a great success. Others Who Have Made a Difference Tom Lane wrote the second-largest help chapter, General JPEG Questions & Answers, and deserves some additional praise for founding and heading the Independent JPEG Group, whose free source code has made the widespread use of JPEG images possible. John Coolidge, I recently discovered, is responsible for sorting and maintaining the burgeoning JPEG image archives at wuarchive.wustl.edu. HereÕs hoping he can find the time (or the help!) to finally get all those pictures sorted! More than 950 registered JPEGView users have so far taken the time to send in their postcards and letters, and believe me, the response has kept me going Ñ keep Õem coming! Finally, I want to thank my wonderful wife Shanti, for being (relatively) understanding and even supportive of my programming addiction/obsession. \ No newline at end of file diff --git a/Resources/Help Text/16.Program History b/Resources/Help Text/16.Program History new file mode 100644 index 0000000..c8deabd --- /dev/null +++ b/Resources/Help Text/16.Program History @@ -0,0 +1 @@ +Program History Version 3.3 (May, 1994) ¥ Added support for dragging selected portions of images to other applications. ¥ Added drag-and-drop support for comments and statistics text. ¥ Added the ability to drag folders from the Finder into the Slide Show Options dialog. ¥ Progress displays are now updated more frequently. ¥ Added support for the Independent JPEG GroupÕs code as an option. ¥ Added proportional and non-dog-eared icon styles. ¥ Changed the scale AppleScript property to accept integers to set scaling percentage. ¥ Removed the file format popup menu when there is no choice of formats available. ¥ Added the ability to use the current selection for cropping icons and/or images. ¥ Rewrote high quality drawing to be much faster; made very high the new default. ¥ Restored the ability to save cropped images. ¥ Rewrote the marching ants algorithm to be more visible onscreen. ¥ Opening PICTs at something other than 72 dpi now expands them to full size. ¥ Removed the unnecessary use of the Time Manager for timing image drawing. ¥ Fixed the problem where small image files would be incorrectly reported as invalid. ¥ Unresolvable aliases in a slide show folder no longer abort the scan in that folder. ¥ Recompiled the JPEGView JFIF Preview into a true fat component. ¥ Color startup screens are now displayed properly if a B&W version is present. ¥ Revealing part of a window during two-pass color reduction no longer aborts it. ¥ You are no longer asked to insert a disk if the last slide show was on a removable drive. ¥ The internal patch for QuickTime with virtual memory has been improved immensely. ¥ Scaling large images down to icon size should no longer leave occasional black bands. Version 3.2 (March, 1994) ¥ Added support for TIFF baseline and LZW-compressed images. ¥ Added support for BMP images, compressed and uncompressed. ¥ Added support for MacPaint and Startup Screen images. ¥ Added rudimentary printing support. ¥ Added copying to the clipboard as a (memory-intensive) option. ¥ The last slide in a single-pass user-controlled slide show is now displayed. ¥ Cleaned up code for reversing within the slide show to work better. ¥ Re-enabled high quality drawing; JPEGView 3.1 always drew in very high quality. ¥ Colors are now restored when hiding the slide show. ¥ Hiding the slide show no longer crashes the machine. ¥ Better system checking for clean exits on 68000-class machines. ¥ Changed compiler options to work around Gatekeeper Aid conflict. ¥ Loosened up GIF decoding slightly to work with GIFs from some broken encoders. ¥ Fixed crash when reducing 16-bit color pictures. ¥ Real aliases are now stored for the slide show folder. ¥ Incorporated the QuickTime VM extension directly into JPEGView. ¥ Added the ability to save any image in its own format with previews and icons. ¥ Menubar area now gets updated instantly when toggling the menubar. ¥ Lots of internal changes and cleanup for the PowerPC. ¥ Improved floating window handling. Version 3.1 (December, 1993) ¥ Added the ability to work in the background when saving and drawing images. ¥ Redesigned the preferences and slide show options dialogs, making them modeless. ¥ Added a progress dialog and the option to cancel while scanning for slide show images. ¥ Added the slide show controls floating window, allowing point-and-click control. ¥ Added the ability to back up in the slide show, and the new Òpause and hideÓ feature. ¥ Recoded the drawing functions to fix incorrect displays on mixed color/grayscale systems. ¥ Fixed a bug that would crash the slide show under EvenBetterBusError. ¥ Fixed the bug that prevented the ÒRepeat last slide showÓ preference from working. ¥ Coded around the conflict with Connectix PowerBook Utilities. ¥ Sped up saving when creating both previews and icons for an image. ¥ Added the ability to save and recognize color reduction for JFIF images. ¥ Added support for multiple-image/animated GIF files and for GIF89 comments. ¥ Added better recognition of variant PICT formats. ¥ Added automatic width control of the comments window. Version 3.0 (September, 1993) ¥ Full AppleEvent support, providing scripting and recording with AppleScript. ¥ Improved custom dithering, with user-selectable quality settings. ¥ Statistics window now floats above others and has a zoom box. ¥ Added support for reading and displaying comments from JPEG and PICT images. ¥ Slide shows can now render the next image offscreen before display. ¥ Displaying filenames is supported in slide shows. ¥ An indicator of slide show progress has been added. ¥ Added extended balloon help for nearly everything. ¥ Interrupting the slide show now gives you options to continue, end, or change options. ¥ Custom icons can now be created when saving images. ¥ Time is now given to background applications during decompression. ¥ Selections can be made and tracked in full-screen windows. ¥ Select screen area works more precisely. ¥ User-resizing is possible now by dragging the lower-right corner of an image. ¥ Added the ability to customize the use of offscreen bitmaps. ¥ Added a sparse pattern of dots to indicate pending slow updates. ¥ Added decompression time to the Statistics floating window. ¥ A simple new Colors floating window has been added. ¥ Moved cropping functions to the Edit menu. ¥ Fixed the bug that would occasionally cause Out Of Memory errors. ¥ Fixed the problems with offscreen bitmaps containing black areas. ¥ Added custom spinning cursors for long operations. ¥ Made the restoration of colors after closing the last image an option. ¥ Removed the distinction between JFIF and JPEG file typing. ¥ Moved all strings out of the code and into resources. ¥ Single-character keyboard shortcuts have been added for alerts and dialogs. ¥ Dialogs and alerts now appear centered on the monitor which currently has the mouse pointer. ¥ The preferences and slide show dialogs are now movable. ¥ Error messages and alerts have become a little more user-friendly. ¥ The progress dialogs now tell you which image is being worked on. ¥ The help text is now stored in a compressed format. ¥ Measures are explicitly taken to prevent screen savers from taking over during a slide show. ¥ JFIF previews are now supported via the JPEGView JFIF Preview extension. ¥ JFIF previews can now be compressed. ¥ ÒAutomatically Fix File TypesÓ option now works better under A/UX. ¥ Temporary memory is now used in some situations. ¥ The Help window can now be sized and zoomed. ¥ Dithering is now always on by default, unless you uncheck the preferences item Òdither reduced color imagesÓ. ¥ Color accuracy problems when copying from offscreen buffers are gone. ¥ YouÕre not allowed to start the slide show until youÕve selected a valid folder. ¥ Changed the About box. Version 2.0 (November, 1992) ¥ Extensively cleaned up and reorganized the Version 1.1 code. ¥ Added the Colors menu, allowing color palette selection. ¥ Added a dithering option that works. ¥ Added an IJG-based color reduction scheme for 8 and 4 bit systems. ¥ Improved the workings of offscreen bitmaps. ¥ Fixed full screen windows to include the corners of all monitors. ¥ Reorganized and expanded the Statistics window. ¥ Added identification of IJG-produced JFIFs, with estimates for the quality. ¥ Added identification of banding in PICT images. ¥ Added fast GIF decoding and viewing capabilities. ¥ Fixed problems with the progress percentage; added scaling indicator. ¥ Added options to automatically scan and fix file types within JPEGView. ¥ Added support for non-JFIF JPEG images, and identification of Adobe JPEGs. ¥ Reworked and reorganized the preferences options. ¥ Added support for many new preferences relating to the new features. ¥ Broke the on-line help into several sections and added a modeless interface. ¥ Improved slide show to handle color reduction during pauses between slides. ¥ Fixed much of the flakiness in handling large uncompressed PICT images. ¥ Added the ability to load and save custom palettes in PICT images. ¥ Removed support for compression of PICTs. ¥ Added select screen area option. ¥ Added the ability to drag the active selection rectangle. ¥ Modified offscreen bitmap handling to do long updates only after 5 seconds idle time. ¥ Fixed dialog handling to allow quick updates behind dialog boxes. ¥ Added the Import option. ¥ Added the ability to detect QuickTime-created JFIFs. ¥ Provided stronger support for PICTs at resolutions other than 72 dpi. Version 1.1 (July, 1992) ¥ Added support for the automatic Slide Show. ¥ Added Next and Previous items to the Windows menu. ¥ Added options for specifying startup actions. ¥ Added the ability to select PICT as the default output file format. ¥ Added a warning option when the offscreen bitmap cannot be created. ¥ Added support for opening any image in a full screen window automatically. ¥ Changed the way files are saved to prevent data loss when an error occurs. ¥ Fixed a bug that caused the wrong image to sometimes be displayed in full screen. ¥ Fixed the problem that led to occasional crashes on startup. ¥ Put to rest the remaining problems with Open-Wide. Version 1.0 (June, 1992) ¥ Rewrote I/O routines to handle file identification and conversions more cleanly. ¥ Added the ability to open any type of PICT. ¥ Added rudimentary JPEG compression options for uncompressed PICTs. ¥ Added support for opening and saving compressed PICT0 resources. ¥ Added rudimentary support for specifying JPEG compression quality in Preferences. ¥ Added the ability to produce thumbnail sketches in JFIF files. ¥ Added full screen support, and options for automatically using it. ¥ Added explicit support for multiple monitors. ¥ Added View menu, and options for cropping, uncropping, zooming, and rescaling. ¥ Added Statistics window and options for controlling it. ¥ Added creation of offscreen bitmaps for faster window updates. ¥ Made the Help dialog bigger and better, and redesigned the About box. ¥ Added Balloon Help. ¥ Fixed a conflict with the Open-Wide control panel. ¥ Improved memory management. Version 0.9 (March, 1992) ¥ Initial release. \ No newline at end of file diff --git a/Resources/Help Text/Technical Information.TXT b/Resources/Help Text/Technical Information.TXT new file mode 100644 index 0000000..883106d --- /dev/null +++ b/Resources/Help Text/Technical Information.TXT @@ -0,0 +1 @@ +Technical Information This chapter is mostly for those curious about how JPEGView works some of its magic. JPEGView 3.1 contains over 25,000 lines of C code, and over 2,700 lines of 68020 assembly code. The bulk of the assembly code is used for the custom dithering and scaling routines, along with several supplemental functions for color quantization and GIF decoding. GIF viewing GIF viewing. Dithering and drawing Dithering and drawing Converting between PICT and JFIF Converting between PICT and JFIF Floating windows Floating windows. \ No newline at end of file diff --git a/Resources/MenuHelpResources.r b/Resources/MenuHelpResources.r new file mode 100644 index 0000000..589da5f --- /dev/null +++ b/Resources/MenuHelpResources.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #define SystemSevenOrLater 1 #include "SysTypes.r" #include "Types.r" #include "BalloonTypes.r" #include "JPEGView.r.h" #define menuHelpOffset 2000 /***********************************************************************/ /********************** **********************/ /********************** Icon Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rIconMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Crop menu title HMStringResItem { // Square rIconMenu + menuHelpOffset, 1, 0, 0, rIconMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // Square, dog-eared rIconMenu + menuHelpOffset, 3, 0, 0, rIconMenu + menuHelpOffset, 4, 0, 0 }, HMStringResItem { // Proportional rIconMenu + menuHelpOffset, 5, 0, 0, rIconMenu + menuHelpOffset, 6, 0, 0 }, HMStringResItem { // Proportional, dog-eared rIconMenu + menuHelpOffset, 7, 0, 0, rIconMenu + menuHelpOffset, 8, 0, 0 } } }; resource 'STR#' (rIconMenu + menuHelpOffset, purgeable) { { "To create square icons which occupy the full 32x32 square available, choose this item.", "To create square icons which occupy the full 32x32 square available, choose this item." "Checked because this is the current selection.", "To create square icons which occupy the full 32x32 square available, with a small folded-" "over corner (dog ear), choose this item.", "To create square icons which occupy the full 32x32 square available, with a small folded-" "over corner (dog ear), choose this item. Checked because this is the current selection.", "To create icons which are proportional to the imageÕs original dimensions, choose this item.", "To create icons which are proportional to the imageÕs original dimensions, choose this item. " "Checked because this is the current selection.", "To create icons which are proportional to the imageÕs original dimensions, with a small folded-" "over corner (dog ear), choose this item.", "To create icons which are proportional to the imageÕs original dimensions, with a small folded-" "over corner (dog ear), choose this item. Checked because this is the current selection." } }; /***********************************************************************/ /********************** **********************/ /********************** Crop Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rCropMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Crop menu title HMStringResItem { // Nothing rCropMenu + menuHelpOffset, 1, 0, 0, rCropMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // Icon rCropMenu + menuHelpOffset, 3, 0, 0, rCropMenu + menuHelpOffset, 4, 0, 0 }, HMStringResItem { // Image rCropMenu + menuHelpOffset, 5, 0, 0, rCropMenu + menuHelpOffset, 6, 0, 0 } } }; resource 'STR#' (rCropMenu + menuHelpOffset, purgeable) { { "To ignore the currently selected area in the image when saving, choose this item.", "To ignore the currently selected area in the image when saving, choose this item. " "Checked because this is the current selection.", "To use the selected area to indicate where an icon should be derived from, choose " "this item.", "To use the selected area to indicate where an icon should be derived from, choose " "this item. Checked because this is the current selection.", "To use the selected area to crop the image, choose this item.", "To use the selected area to crop the image, choose " "this item. Checked because this is the current selection." } }; /***********************************************************************/ /********************** **********************/ /********************** Save As Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rSaveMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, HMStringResItem { // Defaults rSaveMenu + menuHelpOffset, 1, rSaveMenu + menuHelpOffset, 2, rSaveMenu + menuHelpOffset, 3, 0, 0 }, { } }; resource 'STR#' (rSaveMenu + menuHelpOffset, purgeable) { { "To save the image in the indicated format, choose this item.", "To save the image in the indicated format, choose this item. Not available " "because JPEGView for the most part doesnÕt do file conversions.", "JPEGView will save the image in this format." } }; /***********************************************************************/ /********************** **********************/ /********************** Slide Control Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rSlideControlMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Slide Control menu title HMStringResItem { // User-controlled rSlideControlMenu + menuHelpOffset, 1, 0, 0, rSlideControlMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // Automatic rSlideControlMenu + menuHelpOffset, 3, 0, 0, rSlideControlMenu + menuHelpOffset, 4, 0, 0 } } }; resource 'STR#' (rSlideControlMenu + menuHelpOffset, purgeable) { { "To operate the slide show under user-control, choose this item. You will " "be responsible for controlling the slide showÕs progress.", "To operate the slide show under user-control, choose this item. " "Checked because this this is the current selection.", "To run the slide show automatically, with a fixed delay between each " "image, choose this item.", "To run the slide show automatically, with a fixed delay between each " "image, choose this item. Checked because this this is the current " "selection." } }; /***********************************************************************/ /********************** **********************/ /********************** Slide Source Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rSlideSourceMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Slide Control menu title HMStringResItem { // Images in Memory rSlideSourceMenu + menuHelpOffset, 1, 0, 0, rSlideSourceMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // Images from Disk rSlideSourceMenu + menuHelpOffset, 3, 0, 0, rSlideSourceMenu + menuHelpOffset, 4, 0, 0 } } }; resource 'STR#' (rSlideSourceMenu + menuHelpOffset, purgeable) { { "To view a slide show consisting solely of currently open images, choose " "this item.", "To view a slide show consisting solely of currently open images, choose " "this item. Checked because this this is the current selection.", "To view a slide show consisting of images found in a given folder on a " "disk, choose this item.", "To view a slide show consisting of images found in a given folder on a " "disk, choose this item. Checked because this this is the current " "selection." } }; /***********************************************************************/ /********************** **********************/ /********************** Time Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rTimeMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Time menu title HMStringResItem { // seconds rTimeMenu + menuHelpOffset, 1, 0, 0, rTimeMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // minutes rTimeMenu + menuHelpOffset, 3, 0, 0, rTimeMenu + menuHelpOffset, 4, 0, 0 }, HMStringResItem { // hours rTimeMenu + menuHelpOffset, 5, 0, 0, rTimeMenu + menuHelpOffset, 6, 0, 0 } } }; resource 'STR#' (rTimeMenu + menuHelpOffset, purgeable) { { "To set the units for the slide show delay to seconds, choose this item.", "To set the units for the slide show delay to seconds, choose this item. " "Checked because this this is the current selection.", "To set the units for the slide show delay to minutes, choose this item.", "To set the units for the slide show delay to minutes, choose this item. " "Checked because this this is the current selection.", "To set the units for the slide show delay to hours, choose this item.", "To set the units for the slide show delay to hours, choose this item. " "Checked because this this is the current selection." } }; /***********************************************************************/ /************************* **************************/ /************************* Quality Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (rQualityMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Quality menu title HMStringResItem { rQualityMenu + menuHelpOffset, 1, 0, 0, rQualityMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // High quality rQualityMenu + menuHelpOffset, 3, rQualityMenu + menuHelpOffset, 4, rQualityMenu + menuHelpOffset, 5, 0, 0 }, HMStringResItem { // Normal quality rQualityMenu + menuHelpOffset, 6, 0, 0, rQualityMenu + menuHelpOffset, 7, 0, 0 } } }; resource 'STR#' (rQualityMenu + menuHelpOffset, purgeable) { { "Redraws the active window using Òvery highÓ quality. This uses JPEGViewÕs " "improved dithering with a slower, but extremely accurate scaling " "algorithm.", "Redraws the active window using Òvery highÓ quality. Checked because this " "is the current quality setting for the active window.", "Redraws the active window using ÒhighÓ quality. This uses JPEGViewÕs " "improved dithering together with a fast, medium-quality scaling " "algorithm.", "Redraws the active window using ÒhighÓ quality. Not available because " "high quality only benefits 256-color systems.", "Redraws the active window using ÒhighÓ quality. Checked because this is " "the current quality setting for the active window.", "Redraws the active window using ÒnormalÓ quality. This uses the " "MacintoshÕs built-in dithering and scaling.", "Redraws the active window using ÒnormalÓ quality. Checked because this is " "the current quality setting for the active window." } }; /***********************************************************************/ /********************** **********************/ /********************** Prefs Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rPrefsMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Preferences menu title HMStringResItem { // Windows rPrefsMenu + menuHelpOffset, 1, 0, 0, rPrefsMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // Display options rPrefsMenu + menuHelpOffset, 3, 0, 0, rPrefsMenu + menuHelpOffset, 4, 0, 0 }, HMStringResItem { // Offscreen Bitmaps rPrefsMenu + menuHelpOffset, 5, 0, 0, rPrefsMenu + menuHelpOffset, 6, 0, 0 }, HMStringResItem { // Files rPrefsMenu + menuHelpOffset, 7, 0, 0, rPrefsMenu + menuHelpOffset, 8, 0, 0 }, HMStringResItem { // Startup/Miscellany rPrefsMenu + menuHelpOffset, 9, 0, 0, rPrefsMenu + menuHelpOffset, 10, 0, 0 } } }; resource 'STR#' (rPrefsMenu + menuHelpOffset, purgeable) { { "To display options which allow you to control the size and location of " "new JPEGView windows, choose this item.", "To display options which allow you to control the size and location of " "new JPEGView windows, choose this item. Checked because these options " "are currently visible.", "To display options which allow you to control JPEGViewÕs use of colors and " "dithering, choose this item.", "To display options which allow you to control JPEGViewÕs use of colors and " "dithering, choose this item. Checked because these options are " "currently visible.", "To display options which allow you to control the characteristics of the " "JPEGViewÕs bitmaps, choose this item.", "To display options which allow you to control the characteristics of the " "JPEGViewÕs bitmaps, choose this item. Checked because these options " "are currently visible.", "To display options which allow you to control file type fixing and to " "specify defaults when saving images, choose this item.", "To display options which allow you to control file type fixing and to " "specify defaults when saving images, choose this item. Checked " "because these options are currently visible.", "To display options which allow you to control various other aspects of " "JPEGViewÕs behavior, choose this item.", "To display options which allow you to control various other aspects of " "JPEGViewÕs behavior, choose this item. Checked because these options " "are currently visible." } }; /***********************************************************************/ /********************** **********************/ /********************** Help Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'hmnu' (rHelpMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Help menu title HMStringResItem { // Overview rHelpMenu + menuHelpOffset, 1, 0, 0, rHelpMenu + menuHelpOffset, 1, 0, 0 }, HMStringResItem { // Viewing Images rHelpMenu + menuHelpOffset, 2, 0, 0, rHelpMenu + menuHelpOffset, 2, 0, 0 }, HMStringResItem { // Viewing Images rHelpMenu + menuHelpOffset, 3, 0, 0, rHelpMenu + menuHelpOffset, 3, 0, 0 }, HMStringResItem { // Special Effects rHelpMenu + menuHelpOffset, 4, 0, 0, rHelpMenu + menuHelpOffset, 4, 0, 0 }, HMStringResItem { // Colors And Quantization rHelpMenu + menuHelpOffset, 5, 0, 0, rHelpMenu + menuHelpOffset, 5, 0, 0 }, HMStringResItem { // Saving Images rHelpMenu + menuHelpOffset, 6, 0, 0, rHelpMenu + menuHelpOffset, 6, 0, 0 }, HMStringResItem { // Slide Show rHelpMenu + menuHelpOffset, 7, 0, 0, rHelpMenu + menuHelpOffset, 7, 0, 0 }, HMStringResItem { // Preferences Settings rHelpMenu + menuHelpOffset, 8, 0, 0, rHelpMenu + menuHelpOffset, 8, 0, 0 }, HMStringResItem { // File Formats And File Types rHelpMenu + menuHelpOffset, 9, 0, 0, rHelpMenu + menuHelpOffset, 9, 0, 0 }, HMStringResItem { // Scripting JPEGView rHelpMenu + menuHelpOffset, 10, 0, 0, rHelpMenu + menuHelpOffset, 10, 0, 0 }, HMStringResItem { // General JPEG Questions & Answers rHelpMenu + menuHelpOffset, 11, 0, 0, rHelpMenu + menuHelpOffset, 11, 0, 0 }, HMStringResItem { // JPEGView Questions & Answers rHelpMenu + menuHelpOffset, 12, 0, 0, rHelpMenu + menuHelpOffset, 12, 0, 0 }, HMStringResItem { // Hints And Tips rHelpMenu + menuHelpOffset, 13, 0, 0, rHelpMenu + menuHelpOffset, 13, 0, 0 }, HMStringResItem { // Where To Send Those Postcards rHelpMenu + menuHelpOffset, 14, 0, 0, rHelpMenu + menuHelpOffset, 14, 0, 0 }, HMStringResItem { // Acknowledgements rHelpMenu + menuHelpOffset, 15, 0, 0, rHelpMenu + menuHelpOffset, 15, 0, 0 }, HMStringResItem { // Program History rHelpMenu + menuHelpOffset, 16, 0, 0, rHelpMenu + menuHelpOffset, 16, 0, 0 } } }; resource 'STR#' (rHelpMenu + menuHelpOffset, purgeable) { { "Gives a brief overview of JPEGViewÕs features and describes whatÕs new in this " "latest release.", "Describes the process of viewing images, including explanations " "of fast and slow window updating.", "Describes the use and operation of JPEGViewÕs floating windows.", "Describes the various viewing options available in the Edit and View menus, " "including full screen windows and cropped images.", "Provides an explanation of JPEGViewÕs use of color as well as a " "brief explanation of the Macintosh video model and of how " "dithering works.", "Explains JPEGViewÕs options for saving images.", "Describes the various parameters you can control from within " "the Slide Show options dialog.", "Explains the various preferences options and how they affect " "JPEGViewÕs operation.", "Gives an overview of how file types are determined and of what " "file types are supported by JPEGView.", "Provides a brief introduction of scripting using AppleScript and JPEGView.", "Provides excerpts from the JPEG Frequently Asked Questions list, " "compiled by Tom Lane of the Independent JPEG Group.", "Answers a number of commonly-asked questions concerning " "JPEGViewÕs operation.", "Lists a few important and useful techniques for getting the most " "out of JPEGViewÕs features.", "JPEGView is postcardware. This section tells you where to send " "the postcards and why I would like to hear from you.", "Thanks to all those responsible for helping me get JPEGView off " "the ground!", "Lists in excruciating detail what changes were made between the " "different versions of JPEGView." } }; /***********************************************************************/ /************************* **************************/ /************************* Apple Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (rAppleMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { hmnuBlankItem, // Apple menu title HMStringResItem { // About JPEGView... rAppleMenu + menuHelpOffset, 1, rAppleMenu + menuHelpOffset, 2, 0, 0, 0, 0 }, HMStringResItem { // About JPEGView Help... rAppleMenu + menuHelpOffset, 3, rAppleMenu + menuHelpOffset, 4, 0, 0, 0, 0 } } }; resource 'STR#' (rAppleMenu + menuHelpOffset, purgeable) { { "Displays information about JPEGView, including credits if you show the " "statistics floating window.", "Displays information about JPEGView, including credits if you show the " "statistics floating window. Not available because there is a " "dialog box on the screen", "Explains where the online help can be found for those who think " "that Apple put the Help menu there to embarrass them.", "Explains where the online help can be found. " "Not available because there is a dialog box on the screen." } }; /***********************************************************************/ /************************* **************************/ /************************* File Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (rFileMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { HMStringResItem { // File menu title rFileMenu + menuHelpOffset, 1, rFileMenu + menuHelpOffset, 2, rFileMenu + menuHelpOffset, 3, rFileMenu + menuHelpOffset, 4 }, HMStringResItem { // Open... rFileMenu + menuHelpOffset, 5, rFileMenu + menuHelpOffset, 6, 0, 0, 0, 0 }, HMStringResItem { // Import... rFileMenu + menuHelpOffset, 7, rFileMenu + menuHelpOffset, 8, 0, 0, 0, 0 }, HMStringResItem { // Close rFileMenu + menuHelpOffset, 9, rFileMenu + menuHelpOffset, 10, 0, 0, 0, 0 }, HMStringResItem { // Close All rFileMenu + menuHelpOffset, 11, rFileMenu + menuHelpOffset, 12, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Save As... rFileMenu + menuHelpOffset, 13, rFileMenu + menuHelpOffset, 14, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Slide Show... rFileMenu + menuHelpOffset, 15, rFileMenu + menuHelpOffset, 16, 0, 0, 0, 0 }, HMStringResItem { // Begin Slide Show rFileMenu + menuHelpOffset, 17, rFileMenu + menuHelpOffset, 18, 0, 0, 0, 0 }, HMStringResItem { // End Slide Show rFileMenu + menuHelpOffset, 19, rFileMenu + menuHelpOffset, 20, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Page Setup... rFileMenu + menuHelpOffset, 21, 0, 0, 0, 0, 0, 0 }, HMStringResItem { // Print... rFileMenu + menuHelpOffset, 22, rFileMenu + menuHelpOffset, 23, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Preferences... rFileMenu + menuHelpOffset, 24, rFileMenu + menuHelpOffset, 25, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Quit rFileMenu + menuHelpOffset, 26, rFileMenu + menuHelpOffset, 27, 0, 0, 0, 0 } } }; resource 'STR#' (rFileMenu + menuHelpOffset, purgeable) { { "File menu\n\n" "Use this menu to open, close, and save images, as well " "as to access JPEGViewÕs slide show and preferences options.", "File menu\n\n" "This menu is not available because there is a dialog box on the screen.", "File menu\n\n" "This menu is not available because there is a dialog box on the screen.", "This item is not available because there is a dialog box on the screen.", "Opens a new JPEG, GIF, or PICT image.", "Opens a new JPEG, GIF, or PICT image. Not available because there is a " "dialog box on the screen.", "Opens a new image, regardless of what type the Finder thinks it is.", "Opens a new image, regardless of what type the Finder thinks it is. Not " "available because there is a dialog box on the screen.", "Closes the active window.", "Closes the active window. Not available because there are no open " "windows to close.", "Closes all open image windows. This command does not close the Help " "window or any visible floating windows (Statistics, Comments, Colors).", "Closes all open image windows. Not available because there are no open " "images.", "Saves the image in the active window in either PICT, JFIF, or SCRN " "format.", "Saves the image in the active window. Not available because the " "active window does not contain a JPEG image.", "Opens the Slide Show Options dialog, allowing you to specify the settings " "to be used for the next slide show.", "Opens the Slide Show Options dialog, allowing you to specify the settings " "to be used for the next slide show. Not available because there is a " "dialog box on the screen.", "Begins JPEGViewÕs slide show, using the most recent settings.", "Begins JPEGViewÕs slide show, using the most recent settings. Not " "available because the current settings are invalid.", "Brings the current slide show to an end.", "Brings the current slide show to an end. Not available because no slide " "show is currently running.", "Displays a dialog box which allows you to set paper size, orientation, and " "other printing options.", "Prints the current image at its maximum size on a single sheet of paper. You " "can specify printing options (such as the number of copies) in the dialog " "box that appears.", "Prints the current image at its maximum size on a single sheet of paper. Not " "available because the frontmost window does not contain an image.", "Opens the Preferences dialog, allowing you to modify the way JPEGView " "normally works.", "Opens the Preferences dialog, allowing you to modify the way JPEGView " "normally works. Not available because there is a dialog box on the " "screen.", "Closes all open windows and quits JPEGView.", "Closes all open windows and quits JPEGView. Not available because there " "is a dialog box on the screen." } }; /***********************************************************************/ /************************* **************************/ /************************* Edit Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (rEditMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, HMStringResItem { // Defaults 0, 0, rEditMenu + menuHelpOffset, 1, 0, 0, 0, 0 }, { HMStringResItem { // Edit menu title rEditMenu + menuHelpOffset, 2, rEditMenu + menuHelpOffset, 3, rEditMenu + menuHelpOffset, 4, rEditMenu + menuHelpOffset, 5 }, HMStringResItem { // Undo 0, 0, rEditMenu + menuHelpOffset, 6, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Cut rEditMenu + menuHelpOffset, 7, rEditMenu + menuHelpOffset, 8, 0, 0, 0, 0 }, HMStringResItem { // Copy rEditMenu + menuHelpOffset, 9, rEditMenu + menuHelpOffset, 10, 0, 0, 0, 0 }, HMStringResItem { // Cut rEditMenu + menuHelpOffset, 11, rEditMenu + menuHelpOffset, 12, 0, 0, 0, 0 }, HMStringResItem { // Clear rEditMenu + menuHelpOffset, 13, rEditMenu + menuHelpOffset, 14, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Select Screen Area rEditMenu + menuHelpOffset, 15, rEditMenu + menuHelpOffset, 16, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Crop & Zoom rEditMenu + menuHelpOffset, 17, rEditMenu + menuHelpOffset, 18, 0, 0, 0, 0 }, HMStringResItem { // Uncrop Image rEditMenu + menuHelpOffset, 19, rEditMenu + menuHelpOffset, 20, 0, 0, 0, 0 } } }; resource 'STR#' (rEditMenu + menuHelpOffset, purgeable) { { "Not available because JPEGView does not support this function.", "Edit menu\n\n" "Use this menu to cut, copy, and paste text in a dialog box, or to " "perform cropping and zooming operations on an image.", "Edit menu\n\n" "This menu is not available because none of the items pertains to the " "active window.", "Edit menu\n\n" "This menu is not available because there is a dialog box on the screen.", "This item is not available because there is a dialog box on the screen.", "Reverses the effects of the last operation. Not available because " "JPEGView does not support this function.", "Cuts the selected text or graphic, removing it from the document, and " "places it in the Clipboard, making it available for a future Paste " "command.", "Cuts the selected text or graphic, removing it from the document, and " "places it in the Clipboard. Not available because JPEGView does not " "support this function.", "Copies the selected text or graphic and places it in the Clipboard, making " "it available for a future Paste command.", "Copies the selected text or graphic and places it in the Clipboard. Not " "available because JPEGView does not support this function.", "Pastes text or graphics from the Clipboard into the active document.", "Pastes text or graphics from the Clipboard into the active document. Not " "available because JPEGView does not support this function.", "Removes the selected text or graphic without placing it in the Clipboard.", "Removes the selected text or graphic without placing it in the Clipboard. " "Not available because JPEGView does not support this function.", "Selects a screen-sized area of the active window for cropping. Using " "Crop & Zoom on this selection will result in an image sized exactly " "right for your screen, without scaling.", "Selects a screen-sized area of the active window for cropping. " "Not available because this operation is not applicable to the " "active window.", "Crops the selected area to a new window and zooms that window to full " "size, if possible.", "Crops the selected area to a new window and zooms that window to full " "size, if possible. Not available because there is no active graphic " "selection in the active window.", "Removes the cropping from the active image, restoring it to its full " "original size.", "Removes the cropping from the active image, restoring it to its full " "original size. Not available because the active window does not " "contain a cropped image." } }; /***********************************************************************/ /************************* **************************/ /************************* View Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (rViewMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { HMStringResItem { // View menu title rViewMenu + menuHelpOffset, 1, rViewMenu + menuHelpOffset, 2, rViewMenu + menuHelpOffset, 3, rViewMenu + menuHelpOffset, 4 }, HMStringResItem { // Full Screen rViewMenu + menuHelpOffset, 5, rViewMenu + menuHelpOffset, 6, rViewMenu + menuHelpOffset, 7, 0, 0 }, HMSkipItem { }, HMStringResItem { // Resize To Screen rViewMenu + menuHelpOffset, 8, rViewMenu + menuHelpOffset, 9, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Normal Size rViewMenu + menuHelpOffset, 10, rViewMenu + menuHelpOffset, 11, 0, 0, 0, 0 }, HMStringResItem { // Halve Size rViewMenu + menuHelpOffset, 12, rViewMenu + menuHelpOffset, 13, 0, 0, 0, 0 }, HMStringResItem { // Double Size rViewMenu + menuHelpOffset, 14, rViewMenu + menuHelpOffset, 15, 0, 0, 0, 0 }, HMStringResItem { // Maximum Size rViewMenu + menuHelpOffset, 16, rViewMenu + menuHelpOffset, 17, 0, 0, 0, 0 }, HMSkipItem { }, HMStringResItem { // Shrink By 10% rViewMenu + menuHelpOffset, 18, rViewMenu + menuHelpOffset, 19, 0, 0, 0, 0 }, HMStringResItem { // Expand By 10% rViewMenu + menuHelpOffset, 20, rViewMenu + menuHelpOffset, 21, 0, 0, 0, 0 } } }; resource 'STR#' (rViewMenu + menuHelpOffset, purgeable) { { "View menu\n\n" "Use this menu to switch between a normal and a full-screen window " "and to adjust the scaling factor of the active image.", "View menu\n\n" "This menu is not available because the active window does not " "contain an image.", "View menu\n\n" "This menu is not available because there is a dialog box on the screen.", "This item is not available because there is a dialog box on the screen.", "Expands the active window to cover the entire screen, including the " "menubar area. If the image has been scaled, its size will be " "recalculated to utilize the extra area.", "Toggles the active window between a full-screen window and a normal " "window. Not available because the active window does not contain " "an image.", "Shrinks the active window back to a normal-sized window and restores " "the menubar. The image is scaled down to fit the smaller window, if " "necessary.", "Expands the active windowÕs image to its natural size on the current " "monitor.", "Expands the active windowÕs image to its natural size on the current " "monitor. Not available because the active window contains no image.", "Restores the scale factor of the active windowÕs image to 100%. If the " "full-size image does not fit on-screen, it will be scaled downward " "to fit.", "Restores the scale factor of the active windowÕs image to 100%. Not " "available because this operation would have no effect on the active " "window.", "Reduces the scale factor of the active windowÕs image by half.", "Reduces the scale factor of the active windowÕs image by half. Not " "available because this operation would have no effect on the active " "window.", "Doubles the scale factor of the active windowÕs image.", "Doubles the scale factor of the active windowÕs image. Not available " "because this operation would have no effect on the active window.", "Expands the active windowÕs image to its largest possible size within " "the bounds of the current screen.", "Expands the active windowÕs image to its largest possible size within " "the bounds of the current screen. Not available because this operation " "would have no effect on the active window.", "Reduces the scale factor of the active windowÕs image by 10%.", "Reduces the scale factor of the active windowÕs image by 10%. Not " "available because this operation would have no effect on the active " "window.", "Increases the scale factor of the active windowÕs image by 10%.", "Increases the scale factor of the active windowÕs image by 10%. Not " "available because this operation would have no effect on the active " "window." } }; /***********************************************************************/ /************************* **************************/ /************************* Colors Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (rColorsMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { HMStringResItem { // Colors menu title rColorsMenu + menuHelpOffset, 1, rColorsMenu + menuHelpOffset, 2, rColorsMenu + menuHelpOffset, 3, rColorsMenu + menuHelpOffset, 4 }, HMStringResItem { // System Palette rColorsMenu + menuHelpOffset, 5, rColorsMenu + menuHelpOffset, 6, rColorsMenu + menuHelpOffset, 7, 0, 0 }, HMStringResItem { // Grayscale Palette rColorsMenu + menuHelpOffset, 8, rColorsMenu + menuHelpOffset, 9, rColorsMenu + menuHelpOffset, 10, 0, 0 }, HMStringResItem { // Image Palette rColorsMenu + menuHelpOffset, 11, rColorsMenu + menuHelpOffset, 12, rColorsMenu + menuHelpOffset, 13, 0, 0 }, HMStringResItem { // Two-Pass Quantization rColorsMenu + menuHelpOffset, 14, rColorsMenu + menuHelpOffset, 15, rColorsMenu + menuHelpOffset, 16, 0, 0 }, HMSkipItem { }, HMStringResItem { // Dithering rColorsMenu + menuHelpOffset, 17, rColorsMenu + menuHelpOffset, 18, rColorsMenu + menuHelpOffset, 19, 0, 0 }, HMSkipItem { }, HMStringResItem { // Quality 0, 0, rColorsMenu + menuHelpOffset, 20, 0, 0, 0, 0 } } }; resource 'STR#' (rColorsMenu + menuHelpOffset, purgeable) { { "Colors menu\n\n" "Use this menu to select a new set of display colors, or to control " "the dithering or quality of an image.", "Colors menu\n\n" "This menu is not available because the active window does not " "contain an image.", "Colors menu\n\n" "This menu is not available because there is a dialog box on the screen.", "This item is not available because there is a dialog box on the screen.", "Redraws the active window using the standard set of colors that are " "available in the Finder.", "Redraws the active window using the standard set of colors that are " "available in the Finder. Not available because only windows on " "screens with 16 or more colors can use these colors.", "Redraws the active window using the standard set of colors that are " "available in the Finder. Checked because these are the current colors " "for the active window.", "Redraws the active window using an evenly-spaced set of grays.", "Redraws the active window using an evenly-spaced set of grays. Not " "available because only windows on screens with 256 or fewer colors can " "be forced into grayscales.", "Redraws the active window using an evenly-spaced set of grays. Checked " "because these are the current colors for the active window.", "Redraws the active window using the colors stored in the image data.", "Redraws the active window using the colors stored in the image data. " "Not available because no such colors were found.", "Redraws the active window using the colors stored in the image data. " "Redraws the active window using an optimal color set, calculated by " "JPEGView using a two-pass color reduction scheme.", "Redraws the active window using an optimal color set. Not available " "because an optimal color set is only useful for images with Thousands " "or more colors drawn on screens with only 16 or 256 colors available.", "Redraws the active window using an optimal color set, calculated by " "JPEGView using a two-pass color reduction scheme. Checked because " "these are the current colors for the active window.", "Redraws the active window with dithering turned on.", "Toggles dithering on or off for the active window. Not available " "because dithering is unnecessary in the active window.", "Redraws the active window with dithering turned off.", "Redraws the active window with different quality settings. Not " "available because these options are only relevant to screens with " "256 or more colors." } }; /***********************************************************************/ /************************* **************************/ /************************* Window Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (rWindowMenu, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, HMStringResItem { // Defaults rWindowMenu + menuHelpOffset, 1, rWindowMenu + menuHelpOffset, 2, rWindowMenu + menuHelpOffset, 3, 0, 0 }, { HMStringResItem { // Window menu title rWindowMenu + menuHelpOffset, 4, rWindowMenu + menuHelpOffset, 5, rWindowMenu + menuHelpOffset, 6, rWindowMenu + menuHelpOffset, 7 }, HMCompareItem { // Show Statistics "Show Statistics", HMStringResItem { // Statistics rWindowMenu + menuHelpOffset, 8, rWindowMenu + menuHelpOffset, 9, 0, 0, 0, 0 }, }, HMCompareItem { // Hide Statistics "Hide Statistics", HMStringResItem { // Statistics rWindowMenu + menuHelpOffset, 10, rWindowMenu + menuHelpOffset, 11, 0, 0, 0, 0 }, }, HMCompareItem { // Show Comments "Show Comments", HMStringResItem { // Statistics rWindowMenu + menuHelpOffset, 12, rWindowMenu + menuHelpOffset, 13, 0, 0, rWindowMenu + menuHelpOffset, 14 }, }, HMCompareItem { // Hide Comments "Hide Comments", HMStringResItem { // Statistics rWindowMenu + menuHelpOffset, 15, rWindowMenu + menuHelpOffset, 16, 0, 0, rWindowMenu + menuHelpOffset, 17 }, }, HMCompareItem { // Show Colors "Show Colors", HMStringResItem { // Statistics rWindowMenu + menuHelpOffset, 18, rWindowMenu + menuHelpOffset, 19, 0, 0, 0, 0 }, }, HMCompareItem { // Hide Colors "Hide Colors", HMStringResItem { // Statistics rWindowMenu + menuHelpOffset, 20, rWindowMenu + menuHelpOffset, 21, 0, 0, 0, 0 }, }, HMSkipItem { }, HMStringResItem { // Previous Image rWindowMenu + menuHelpOffset, 22, rWindowMenu + menuHelpOffset, 23, 0, 0, 0, 0 }, HMStringResItem { // Next Image rWindowMenu + menuHelpOffset, 24, rWindowMenu + menuHelpOffset, 25, 0, 0, 0, 0 }, HMSkipItem { } } }; resource 'STR#' (rWindowMenu + menuHelpOffset, purgeable) { { "Brings the window for this image to the front.", "Brings the window for this image to the front. This item is not available " "because there is a dialog box on the screen.", "Brings the window for this image to the front. Checked because this window " "is currently the active window.", "Window menu\n\n" "Use this menu to switch between JPEGViewÕs currently open windows " "and to toggle the visibility of the Statistics, Comments, and Colors " "floating windows.", "Window menu\n\n" "This menu is not available because there is a dialog box on the screen.", "Window menu\n\n" "This menu is not available because there is a dialog box on the screen.", "This item is not available because there is a dialog box on the screen.", "Makes the JPEGView Statistics floating window visible. The Statistics " "floating window displays various pieces of interesting information " "about the active window.", "Makes the JPEGView Statistics floating window visible. Not " "available because there is a dialog box on the screen.", "Hides the JPEGView Statistics floating window.", "Hides the JPEGView Statistics floating window. Not " "available because there is a dialog box on the screen.", "Makes the JPEGView Comments floating window visible. The Comments " "floating window displays any comments associated with the " "active window.", "Makes the JPEGView Comments floating window visible. Not " "available because there is a dialog box on the screen.", "Makes the JPEGView Comments floating window visible. Marked because JPEGView " "found comments stored with the active image.", "Hides the JPEGView Comments floating window.", "Hides the JPEGView Comments floating window. Not " "available because there is a dialog box on the screen.", "Hides the JPEGView Comments floating window. Marked because JPEGView " "found comments stored with the active image.", "Makes the JPEGView Colors floating window visible. The Colors " "floating window displays a sample of the current set of colors " "available for drawing.", "Makes the JPEGView Colors floating window visible. Not " "available because there is a dialog box on the screen.", "Hides the JPEGView Colors floating window.", "Hides the JPEGView Colors floating window. Not " "available because there is a dialog box on the screen.", "Cycles forward through the list of image windows below. If the first " "image is currently in front, this command will bring forward the last " "image in the list.", "Cycles forward through the list of image windows below. Not " "available because there are less than two windows currently open.", "Cycles backward through the list of image windows below. If the last " "image is currently in front, this will bring forward the first " "image in the list.", "Cycles backward through the list of image windows below. Not " "available because there are less than two windows currently open." } }; /***********************************************************************/ /************************* **************************/ /************************* Help Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'hmnu' (kHMHelpMenuID, purgeable) { HelpMgrVersion, hmDefaultOptions, 0, 0, hmnuBlankItem, // Defaults { HMStringResItem { // JPEGView Help... kHMHelpMenuID + menuHelpOffset, 1, kHMHelpMenuID + menuHelpOffset, 2, 0, 0, 0, 0 } } }; resource 'STR#' (kHMHelpMenuID + menuHelpOffset, purgeable) { { "Opens a window containing JPEGViewÕs extensive online help.", "Opens a window containing JPEGViewÕs extensive online help. Not available " "because there is a dialog box on the screen." } }; \ No newline at end of file diff --git a/Resources/MenuResources.r b/Resources/MenuResources.r new file mode 100644 index 0000000..becc874 --- /dev/null +++ b/Resources/MenuResources.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #define SystemSevenOrLater 1 #include "SysTypes.r" #include "Types.r" #include "BalloonTypes.r" #include "JPEGView.r.h" #define menuHelpOffset 2000 /***********************************************************************/ /************************ *************************/ /************************ The Menu Bar *************************/ /************************ *************************/ /***********************************************************************/ resource 'MBAR' (rMenuBar, preload) { { rAppleMenu, rFileMenu, rEditMenu, rViewMenu, rColorsMenu, rWindowMenu } }; /***********************************************************************/ /********************** **********************/ /********************** Icon Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rIconMenu, preload) { rIconMenu, textMenuProc, allEnabled, enabled, "", { "Square", 1, noKey, noMark, plain, "Square, dog-eared", 2, noKey, noMark, plain, "Proportional", 3, noKey, noMark, plain, "Proportional, dog-eared", 4, noKey, noMark, plain } }; /***********************************************************************/ /********************** **********************/ /********************** Crop Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rCropMenu, preload) { rCropMenu, textMenuProc, allEnabled, enabled, "", { "Nothing", noIcon, noKey, noMark, plain, "Icon", noIcon, noKey, noMark, plain, "Image", noIcon, noKey, noMark, plain } }; /***********************************************************************/ /********************** **********************/ /********************** Save As Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rSaveMenu, preload) { rSaveMenu, textMenuProc, allEnabled, enabled, "", { } }; /***********************************************************************/ /********************** **********************/ /********************** Slide Control Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rSlideControlMenu, preload) { rSlideControlMenu, textMenuProc, allEnabled, enabled, "", { "User-controlled", noIcon, noKey, noMark, plain, "Automatic", noIcon, noKey, noMark, plain } }; /***********************************************************************/ /********************** **********************/ /********************** Slide Source Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rSlideSourceMenu, preload) { rSlideSourceMenu, textMenuProc, allEnabled, enabled, "", { "Images in Memory", noIcon, noKey, noMark, plain, "Images from Disk", noIcon, noKey, noMark, plain } }; /***********************************************************************/ /********************** **********************/ /********************** Time Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rTimeMenu, preload) { rTimeMenu, textMenuProc, allEnabled, enabled, "", { "seconds", noIcon, noKey, noMark, plain, "minutes", noIcon, noKey, noMark, plain, "hours", noIcon, noKey, noMark, plain, } }; /***********************************************************************/ /************************* **************************/ /************************* Quality Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'MENU' (rQualityMenu, preload) { rQualityMenu, customMenuProc, allEnabled, enabled, "", { "Very High", noIcon, "V", noMark, shift, "High", noIcon, "H", noMark, shift, "Normal", noIcon, "N", noMark, shift, } }; /***********************************************************************/ /********************** **********************/ /********************** Prefs Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rPrefsMenu, preload) { rPrefsMenu, textMenuProc, allEnabled, enabled, "Preferences", { "Windows", noIcon, noKey, noMark, plain, "Display", noIcon, noKey, noMark, plain, "Bitmaps", noIcon, noKey, noMark, plain, "Files", noIcon, noKey, noMark, plain, "Miscellany", noIcon, noKey, noMark, plain, } }; /***********************************************************************/ /********************** **********************/ /********************** Help Pop-Up Menu **********************/ /********************** **********************/ /***********************************************************************/ resource 'MENU' (rHelpMenu, preload) { rHelpMenu, textMenuProc, allEnabled, enabled, "", { "Introduction", noIcon, noKey, noMark, plain, "Viewing Images", noIcon, noKey, noMark, plain, "The How and Why of Floating Windows", noIcon, noKey, noMark, plain, "Special Effects", noIcon, noKey, noMark, plain, "Colors And Color Reduction", noIcon, noKey, noMark, plain, "Saving Images", noIcon, noKey, noMark, plain, "Slide Show", noIcon, noKey, noMark, plain, "Preferences Settings", noIcon, noKey, noMark, plain, "File Formats and File Types", noIcon, noKey, noMark, plain, "Scripting JPEGView", noIcon, noKey, noMark, plain, "General JPEG Questions & Answers", noIcon, noKey, noMark, plain, "JPEGView Questions & Answers", noIcon, noKey, noMark, plain, "Hints And Tips", noIcon, noKey, noMark, plain, "Contacting the Author", noIcon, noKey, noMark, plain, "Acknowledgments", noIcon, noKey, noMark, plain, "Program History", noIcon, noKey, noMark, plain } }; /***********************************************************************/ /************************* **************************/ /************************* Apple Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'MENU' (rAppleMenu, preload) { rAppleMenu, customMenuProc, 0b1111111111111111111111111111011, enabled, apple, { "About JPEGView", noIcon, noKey, noMark, plain, "About JPEGView Help", noIcon, noKey, noMark, plain, "-", noIcon, noKey, noMark, plain } }; /***********************************************************************/ /************************* **************************/ /************************* File Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'MENU' (rFileMenu, preload) { rFileMenu, customMenuProc, 0b1111111111111111110010010000011, enabled, "File", { "Open...", noIcon, "O", noMark, plain, "Import...", noIcon, "O", noMark, shift, "Close", noIcon, "W", noMark, plain, "Close All Images", noIcon, "W", noMark, shift, "-", noIcon, noKey, noMark, plain, "Save As...", noIcon, "S", noMark, plain, "-", noIcon, noKey, noMark, plain, "Slide Show Options", noIcon, "I", noMark, plain, "Begin Slide Show", noIcon, "I", noMark, shift, "End Slide Show", noIcon, ".", noMark, plain, "-", noIcon, noKey, noMark, plain, "Page Setup...", noIcon, noKey, noMark, plain, "Print...", noIcon, "P", noMark, plain, "-", noIcon, noKey, noMark, plain, "Preferences", noIcon, noKey, noMark, plain, "-", noIcon, noKey, noMark, plain, "Quit", noIcon, "Q", noMark, plain } }; /***********************************************************************/ /************************* **************************/ /************************* Edit Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'MENU' (rEditMenu, preload) { rEditMenu, customMenuProc, 0b1111111111111111111100000000000, disabled, "Edit", { "Undo", noIcon, "Z", noMark, plain, "-", noIcon, noKey, noMark, plain, "Cut", noIcon, "X", noMark, plain, "Copy", noIcon, "C", noMark, plain, "Paste", noIcon, "V", noMark, plain, "Clear", noIcon, noKey, noMark, plain, "-", noIcon, noKey, noMark, plain, "Select Screen Area", noIcon, "A", noMark, plain, "-", noIcon, noKey, noMark, plain, "Crop & Zoom", noIcon, "R", noMark, plain, "Uncrop", noIcon, "U", noMark, plain, } }; /***********************************************************************/ /************************* **************************/ /************************* View Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'MENU' (rViewMenu, preload) { rViewMenu, customMenuProc, 0b1111111111111111111111011110101, disabled, "View", { "Full Screen", noIcon, "F", noMark, plain, "-", noIcon, noKey, noMark, plain, "Resize To Screen", noIcon, "E", noMark, plain, "-", noIcon, noKey, noMark, plain, "Normal Size", noIcon, "L", noMark, plain, "Halve Size", noIcon, "H", noMark, plain, "Double Size", noIcon, "D", noMark, plain, "Maximum Size", noIcon, "M", noMark, plain, "-", noIcon, noKey, noMark, plain, "Shrink By 10%", noIcon, "[", noMark, plain, "Expand By 10%", noIcon, "]", noMark, plain } }; /***********************************************************************/ /************************* **************************/ /************************* Colors Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'MENU' (rColorsMenu, preload) { rColorsMenu, customMenuProc, 0b1111111111111111111111110101111, disabled, "Colors", { "System Colors", noIcon, "Y", noMark, plain, "Grayscales", noIcon, "G", noMark, plain, "Image Colors", noIcon, "J", noMark, plain, "Two-Pass Color Reduction", noIcon, "T", noMark, plain, "-", noIcon, noKey, noMark, plain, "Dithering", noIcon, "B", noMark, plain, "-", noIcon, noKey, noMark, plain, "Quality", noIcon, hierarchicalMenu, rQualityMenuID, plain } }; /***********************************************************************/ /************************* **************************/ /************************* Window Menu **************************/ /************************* **************************/ /***********************************************************************/ resource 'MENU' (rWindowMenu, preload) { rWindowMenu, customMenuProc, 0b1111111111111111111111110000111, enabled, "Window", { "Show Statistics", noIcon, "0", noMark, plain, "Show Comments", noIcon, "`", noMark, plain, "Show Colors", noIcon, "\\", noMark, plain, "-", noIcon, noKey, noMark, plain, "Previous Image", noIcon, "-", noMark, plain, "Next Image", noIcon, "+", noMark, plain } }; /***********************************************************************/ /************************* **************************/ /************************* Help Menu **************************/ /************************* **************************/ /***********************************************************************/ \ No newline at end of file diff --git a/Resources/PowerPCResources.r b/Resources/PowerPCResources.r new file mode 100644 index 0000000..03a97f8 --- /dev/null +++ b/Resources/PowerPCResources.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #define SystemSevenOrLater 1 #include "JPEGView.r.h" #include "CodeFragmentTypes.r" #include "Types.r" resource 'cfrg' (0) { { kPowerPC, kFullLib, kNoVersionNum, kNoVersionNum, kDefaultStackSize, kNoAppSubFolder, kIsApp, kOnDiskFlat, kZeroOffset, kWholeFork, "JPEGView" } }; #ifdef PPC resource 'ALRT' (rPowerPCAlert, preload) { { 100, 100, 215, 410 }, rPowerPCAlert, beepStages, noAutoCenter }; resource 'DITL' (rPowerPCAlert, preload) { { { 85, 225, 105, 300 }, Button { enabled, "Finder" }, { 8, 75, 75, 300 }, StaticText { disabled, "Sorry, this version of JPEGView requires " "a PowerPC Macintosh to run." }, } }; #endif \ No newline at end of file diff --git a/Resources/aeteResource.r b/Resources/aeteResource.r new file mode 100644 index 0000000..7a9adf3 --- /dev/null +++ b/Resources/aeteResource.r @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for standard resource types //===================================================================================== #include "AEUserTermTypes.r" #include "AppleEvents.r" #include "AEObjects.r" #include "AERegistry.r" //===================================================================================== // Includes specific to JPEGView //===================================================================================== #include "JPEGView.r.h" #ifndef reserved #define reserved false #endif //===================================================================================== // The AppleEvent terminology extension (aete) resource //===================================================================================== resource 'aete' (0, purgeable) { 0x01, 0x00, english, roman, { //===================================================================================== // Supported events from the Required Suite //===================================================================================== "Required Suite", "Terms that every application should support", kAERequiredSuite, 1, 1, { "open", "Open the specified object(s)", kCoreEventClass, kAEOpenDocuments, noReply, "", replyOptional, singleItem, notEnumerated, res13, typeAlias, "list of objects to open", directParamRequired, listOfItems, notEnumerated, changesState, res12, { // parameter extensions "on", keyOpenScreen, enumOpenScreen, "Monitor on which to open the documents", optional, singleItem, enumerated, res13, "using full screen", keyOpenFull, enumOpenFull, "Qualifications for using full screen windows", optional, singleItem, enumerated, res13, "expansion", keyAutoExpand, typeBoolean, "Expand small images to maximum size?", optional, singleItem, notEnumerated, res13, "visible", keyVisible, typeBoolean, "Make windows visible immediately?", optional, singleItem, notEnumerated, res13, "with colors", keyOpenPalette, enumOpenPalette, "Suggested palette use for new images", optional, singleItem, enumerated, res13, "with quality", keyOpenQuality, enumDrawQuality, "Scaling and dithering quality to use", optional, singleItem, enumerated, res13, "bitmaps", keyOpenBitmaps, typeBoolean, "Require an offscreen bitmap?", optional, singleItem, notEnumerated, res13, "comments", keyAutoComments, typeBoolean, "Show image comments if available?", optional, singleItem, notEnumerated, res13, "type fixing", keyFixTypes, typeBoolean, "Fix any incorrect file types?", optional, singleItem, notEnumerated, res13, "changing creators", keyChangeCreator, typeBoolean, "Change creator when fixing file types?", optional, singleItem, notEnumerated, res13, "no errors", keyNoErrors, typeBoolean, "Don't report errors directly to the user?", optional, singleItem, notEnumerated, res13 }, }, { // class extensions }, { // comparator extensions }, { // enumerator extensions }, //===================================================================================== // Supported events from the Core Suite //===================================================================================== "Standard Suite", "Common terms for most applications", 'CoRe', 1, 1, { "close", "Close an object", kAECoreSuite, kAEClose, noReply, "", replyOptional, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object to close", directParamRequired, singleItem, notEnumerated, changesState, res12, { "saving", keyAESaveOptions, enumSaveOptions, "specifies whether changes should be saved before closing", optional, singleItem, enumerated, res13, "saving in", keyAEFile, typeAlias, "the file in which to save the object", optional, singleItem, notEnumerated, res13, "restore colors", keyRestoreColors, typeBoolean, "specifies whether to restore system colors if closing last document", optional, singleItem, notEnumerated, res13 }, "count", "Return the number of elements of a particular class within an object", kAECoreSuite, kAECountElements, typeLongInteger, "the number of elements", replyRequired, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object whose elements are to be counted", directParamRequired, singleItem, notEnumerated, doesntChangeState, res12, { "each", keyAEObjectClass, typeType, "the class of the elements to be counted.", required, singleItem, notEnumerated, res13 }, "data size", "Return the size in bytes of an object", kAECoreSuite, kAEGetDataSize, typeLongInteger, "the size of the object in bytes", replyRequired, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object whose data size is to be returned", directParamRequired, singleItem, notEnumerated, doesntChangeState, res12, { "as", keyAERequestedType, typeType, "the data type for which the size is calculated", optional, singleItem, notEnumerated, res13 }, "delete", "Delete an element from an object", kAECoreSuite, kAEDelete, noReply, "", replyOptional, singleItem, notEnumerated, res13, typeObjectSpecifier, "the element to delete", directParamRequired, singleItem, notEnumerated, changesState, res12, { }, "duplicate", "Duplicate object(s)", kAECoreSuite, kAEClone, typeObjectSpecifier, "to the duplicated object(s)", replyRequired, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object(s) to duplicate", directParamRequired, singleItem, notEnumerated, changesState, res12, { "to", keyAEInsertHere, typeInsertionLoc, "the new location for the object(s)", optional, singleItem, notEnumerated, res13, "visible", keyVisible, typeBoolean, "specifies whether the duplicated object(s) should be made visible", optional, singleItem, notEnumerated, res13 }, "exists", "Verify if an object exists", kAECoreSuite, kAEDoObjectsExist, typeBoolean, "true if it exists, false if not", replyRequired, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object in question", directParamRequired, singleItem, notEnumerated, doesntChangeState, res12, { }, "get", "Get the data for an object", kAECoreSuite, kAEGetData, typeWildCard, "The data from the object", replyRequired, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object whose data is to be returned", directParamRequired, singleItem, notEnumerated, doesntChangeState, res12, { "as", keyAERequestedType, typeType, "the desired types for the data, in order of preference", optional, listOfItems, notEnumerated, res13 }, "make", "Make a new element", kAECoreSuite, kAECreateElement, typeObjectSpecifier, "to the new object(s)", replyRequired, singleItem, notEnumerated, res13, noParams, "", directParamOptional, singleItem, notEnumerated, changesState, res12, { "new", keyAEObjectClass, typeType, "the class of the new element.", required, singleItem, notEnumerated, res13, "at", keyAEInsertHere, typeInsertionLoc, "the location at which to insert the element", required, singleItem, notEnumerated, res13, "with data", keyAEData, typeWildCard, "the initial data for the element", optional, singleItem, notEnumerated, res13, "with properties", keyAEPropData, typeAERecord, "the initial values for the properties of the element", optional, singleItem, notEnumerated, res13 }, "move", "Move object(s) to a new location", kAECoreSuite, kAEMove, typeObjectSpecifier, "to the object(s) after they have been moved", replyRequired, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object(s) to move", directParamRequired, singleItem, notEnumerated, changesState, res12, { "to", keyAEInsertHere, typeInsertionLoc, "the new location for the object(s)", required, singleItem, notEnumerated, res13 }, "save", "Save an object", kAECoreSuite, kAESave, noReply, "", replyOptional, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object to save", directParamRequired, singleItem, notEnumerated, changesState, res12, { "in", keyAEFile, typeAlias, "the file in which to save the object", optional, singleItem, notEnumerated, res13, "as", keyAEFileType, typeType, "the file type of the document in which to save the data", optional, singleItem, notEnumerated, res13, "preview", keyCreatePreview, typeBoolean, "specifies whether to save a preview of the document", optional, singleItem, notEnumerated, res13, "reduced colors", keySaveQuant, typeBoolean, "specifies whether to save a reduced color set with the document", optional, singleItem, notEnumerated, res13, "icons", keyMakeIcons, typeBoolean, "specifies whether to create custom icons for the document", optional, singleItem, notEnumerated, res13 }, "set", "Set an objectÕs data", kAECoreSuite, kAESetData, noReply, "", replyOptional, singleItem, notEnumerated, res13, typeObjectSpecifier, "the object to change", directParamRequired, singleItem, notEnumerated, changesState, res12, { "to", keyAEData, typeWildCard, "the new value", required, singleItem, notEnumerated, res13 } }, //===================================================================================== // Supported classes from the Core Suite //===================================================================================== { "application", cApplication, "An application program", { "clipboard", pClipboard, typeWildCard, "the clipboard", reserved, listOfItems, notEnumerated, readOnly, res12, "frontmost", pIsFrontProcess, typeBoolean, "Is this the frontmost application?", reserved, singleItem, notEnumerated, readOnly, res12, "name", pName, typeIntlText, "the name", reserved, singleItem, notEnumerated, readOnly, res12, "selection", pSelection, cSelection, "the selection visible to the user", reserved, singleItem, notEnumerated, readOnly, res12, "version", pVersion, typeLongInteger, "the version of the application", reserved, singleItem, notEnumerated, readOnly, res12 }, { cWindow, { formAbsolutePosition, formName }, cDocument, { formAbsolutePosition, formName } }, "applications", cApplication, "Every application", { "class attributes", kAESpecialClassProperties, typeType, "special class attributes", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural }, { }, "document", cDocument, "A document", { "modified", pIsModified, typeBoolean, "Has the document been modified since the last save?", reserved, singleItem, notEnumerated, readOnly, res12, "name", pName, cIntlText, "the name", reserved, singleItem, notEnumerated, readWrite, res12, "selection", pSelection, cSelection, "the selection visible to the user", reserved, singleItem, notEnumerated, readOnly, res12 }, { cImage, { formAbsolutePosition }, cFile, { formAbsolutePosition } }, "documents", cDocument, "Every document", { "class attributes", kAESpecialClassProperties, typeType, "special class attributes", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural }, { }, "file", cFile, "A file", { "stationery", pIsStationeryPad, cBoolean, "Is the file a stationery file?", reserved, singleItem, notEnumerated, readOnly, res12, "name", pName, cIntlText, "the name", reserved, singleItem, notEnumerated, readWrite, res12 }, { cImage, { formAbsolutePosition } }, "files", cFile, "Every file", { "class attributes", kAESpecialClassProperties, typeType, "special class attributes", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural }, { }, "selection-object", cSelection, "the selection visible to the user", { "bounds", pBounds, cQDRectangle, "the bounding rectangle of the selection", reserved, singleItem, notEnumerated, readWrite, res12 }, { }, "window", cWindow, "A window", { "bounds", pBounds, cQDRectangle, "the boundary rectangle for the window", reserved, singleItem, notEnumerated, readWrite, res12, "closeable", pHasCloseBox, typeBoolean, "Does the window have a close box?", reserved, singleItem, notEnumerated, readOnly, res12, "titled", pHasTitleBar, typeBoolean, "Does the window have a title bar?", reserved, singleItem, notEnumerated, readOnly, res12, "index", pIndex, typeLongInteger, "the number of the window", reserved, singleItem, notEnumerated, readWrite, res12, "floating", pIsFloating, typeBoolean, "Does the window float?", reserved, singleItem, notEnumerated, readOnly, res12, "modal", pIsModal, typeBoolean, "Is the window modal?", reserved, singleItem, notEnumerated, readOnly, res12, "resizable", pIsResizable, typeBoolean, "Is the window resizable?", reserved, singleItem, notEnumerated, readOnly, res12, "zoomable", pIsZoomable, typeBoolean, "Is the window zoomable?", reserved, singleItem, notEnumerated, readOnly, res12, "zoomed", pIsZoomed, typeBoolean, "Is the window zoomed?", reserved, singleItem, notEnumerated, readWrite, res12, "name", pName, cIntlText, "the title of the window", reserved, singleItem, notEnumerated, readWrite, res12, "selection", pSelection, cSelection, "the selection visible to the user", reserved, singleItem, notEnumerated, readOnly, res12, "visible", pVisible, typeBoolean, "Is the window visible?", reserved, singleItem, notEnumerated, readWrite, res12, "full screen", pFullScreen, cBoolean, "Is the window full-screen?", reserved, singleItem, notEnumerated, readWrite, res12, "contents", pWindowType, enumWindowType, "the contents of the window", reserved, singleItem, enumerated, readOnly, res12 }, { cDocument, { formAbsolutePosition }, cDrawingArea, { formAbsolutePosition } }, "windows", cWindow, "Every window", { "class attributes", kAESpecialClassProperties, typeType, "special class attributes", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural }, { }, "insertion point", cInsertionLoc, "An insertion location", { }, { }, "insertion points", cInsertionLoc, "Every insertion location", { "class attributes", kAESpecialClassProperties, typeType, "special class attributes", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural, }, { } }, { }, //===================================================================================== // Supported enumerators from the Core Suite //===================================================================================== { enumSaveOptions, { "yes", kAEYes, "Save objects now", "no", kAENo, "Do not save objects", "ask", kAEAsk, "Ask the user whether to save" }, enumKeyForm, { "index", formAbsolutePosition, "keyform designating indexed access", "named", formName, "keyform designating named access" }, enumWindowType, { "image", kAEWTImage, "an image window", "full screen image", kAEWTFullImage, "a full screen image window", "statistics", kAEWTStatistics, "the statistics floating window", "image comments", kAEWTComments, "the comments floating window", "image colors", kAEWTColors, "the colors floating window", "help text", kAEWTHelp, "the help window", "slide show options", kAEWTSlideShow, "the slide show options dialog", "preferences", kAEWTPreferences, "the preferences dialog", "about box", kAEWTAbout, "the about box", "slide show controls", kAEWTSlideControls, "the slide show controls floating window", "about help", kAEWTAboutHelp, "the about JPEGView help window" }, enumOpenScreen, { "deepest color", kAEOSDeepestColor, "deepest color monitor", "deepest grayscale", kAEOSDeepestGray, "deepest grayscale monitor", "largest color", kAEOSLargestColor, "largest color monitor", "largest grayscale", kAEOSLargestGray, "largest grayscale monitor", "main", kAEOSMain, "main (menubar) monitor" }, enumOpenFull, { "always", kAEOFAlways, "Always use full screen windows", "always if large", kAEOFAlwaysIfLarge, "Use full screen windows for large images", "on request if large", kAEOFAskIfLarge, "Ask to use full screen windows for large images", "never", kAEOFNever, "Never use full screen windows" }, enumOpenPalette, { "image or reduced or system", kAEOPImageQuantScrn, "Try image colors, then reduced colors, then current colors", "reduced or image or system", kAEOPQuantImageScrn, "Try reduced colors, then image colors, then current colors", "image or system", kAEOPImageScrn, "Try image colors, then current colors", "reduced or system", kAEOPQuantScrn, "Try reduced colors, then current colors", "system", kAEOPScrn, "Use only current colors" } }, //===================================================================================== // Supported classes from the QuickDraw Graphics Suite //===================================================================================== "QuickDraw Graphics Suite", "A set of basic classes for graphics", 'QdRw', 1, 1, { }, // events { // classes "drawing area", cDrawingArea, "A drawing area", { "bounds", pBounds, cQDRectangle, "the rectangle that contains the drawing area", reserved, singleItem, notEnumerated, readWrite, res12, "colors", pPalette, enumPalette, "the current color set", reserved, singleItem, enumerated, readWrite, res12, "color table", pColorTable, cColorTable, "the color table", reserved, singleItem, notEnumerated, readWrite, res12, "scale", pScale, typeShortInteger, "the default scaling for objects in the drawing area (in percent)", reserved, singleItem, notEnumerated, readWrite, res12, "quality", pDrawQuality, enumDrawQuality, "the scaling and dithering quality", reserved, singleItem, enumerated, readWrite, res12, "transfer mode", pTransferMode, enumTransferMode, "the transfer mode", reserved, singleItem, notEnumerated, readWrite, res12 }, { cImage, { formAbsolutePosition } }, "drawing areas", cDrawingArea, "Every drawing area", { "", kAESpecialClassProperties, typeType, "", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural }, { }, "pixel map", cPixelMap, "A pixel map", { "bounds", pBounds, cQDRectangle, "the smallest rectangle that contains the pixel map", reserved, singleItem, notEnumerated, readOnly, res12, "pixel depth", pPixelDepth, cShortInteger, "bits per pixel", reserved, singleItem, notEnumerated, readOnly, res12 }, { }, "pixel maps", cPixelMap, "Every pixel map", { "", kAESpecialClassProperties, typeType, "", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural }, { } }, { }, // comparators //===================================================================================== // Supported enumerators from the QuickDraw Graphics Suite //===================================================================================== { // enumerators enumTransferMode, { "no dithering", kAEQDCopy, "", "dithering", kAEQDDitherCopy, "" }, enumPalette, { "system colors", kAEPSystem, "The usual system colors", "grayscales", kAEPGrayscale, "Evenly-spaced levels of gray", "image colors", kAEPImage, "The imageÕs internally-defined colors", "two pass color reduction", kAEPQuantized, "Two-pass color reduction" }, enumDrawQuality, { "very high", kAEDQVeryHigh, "High-quality scaling and dithering", "high", kAEDQHigh, "High-quality dithering with fast scaling", "normal", kAEDQNormal, "AppleÕs built-in dithering and scaling" } }, //===================================================================================== // Supported events from the Miscellaneous Standards Suite //===================================================================================== "Miscellaneous Standards Suite", "Miscellaneous standard events and classes", 'MiSc', 1, 1, { // events "copy", "Copy the current selection to the clipboard", kAEMiscStandards, kAECopy, noReply, "", replyOptional, singleItem, notEnumerated, res13, noParams, "", directParamOptional, singleItem, notEnumerated, doesntChangeState, res12, { } }, { }, // classes { }, // comparators { }, // enumerators //===================================================================================== // Supported events from the JPEGView Suite //===================================================================================== "JPEGView Suite", "Terms specific to JPEGView", kJPEGViewSuite, 1, 1, { // events "reduce", "Reduce an image to a given number of colors", kJPEGViewSuite, kAEQuantizeImage, typeColorTable, "The reduced color table", replyRequired, singleItem, notEnumerated, res13, typeObjectSpecifier, "The image to be reduced", directParamRequired, singleItem, notEnumerated, changesState, res12, { "to", keyColorCount, typeLongInteger, "The number of colors to reduce to", required, singleItem, notEnumerated, res13 }, "slide show", "Set up and begin a JPEGView slide show", kJPEGViewSuite, kAESlideShow, noReply, "", replyOptional, singleItem, notEnumerated, res13, typeAlias, "List of documents to be used or searched", directParamRequired, listOfItems, notEnumerated, changesState, res12, { "with delay", keyDelay, typeLongInteger, "the delay between successive images", optional, singleItem, notEnumerated, res13, "filenames", keyFilenames, typeBoolean, "Display the filename of each image?", optional, singleItem, notEnumerated, res13, "images from disk", keyFromDisk, typeBoolean, "Create slide show from images on disk?", optional, singleItem, notEnumerated, res13, "no errors", keyIgnoreErrors, typeBoolean, "Ignore minor errors?", optional, singleItem, notEnumerated, res13, "importing", keyImportFiles, typeBoolean, "Import unrecognized files?", optional, singleItem, notEnumerated, res13, "shuffling", keyRandom, typeBoolean, "Display in random order?", optional, singleItem, notEnumerated, res13, "looping", keyRepeat, typeBoolean, "Repeat the show indefinitely?", optional, singleItem, notEnumerated, res13, "recursive scan", keyScanRecursive, typeBoolean, "Scan subfolders recursively?", optional, singleItem, notEnumerated, res13, "user control", keyUserControl, typeBoolean, "Operate under user control?", optional, singleItem, notEnumerated, res13, "offscreen drawing", keyOffscreen, typeBoolean, "Render offscreen before display?", optional, singleItem, notEnumerated, res13, "auto comments", keyAutoComments, typeBoolean, "Show image comments if available?", optional, singleItem, notEnumerated, res13, "hidden windoids", keyHideWindoids, typeBoolean, "Hide the windoids?", optional, singleItem, notEnumerated, res13, "screen saver", keyScreenSaver, typeBoolean, "Abort like a screen saver?", optional, singleItem, notEnumerated, res13, "hidden controls", keyHideControls, typeBoolean, "Keep slide show controls hidden?", optional, singleItem, notEnumerated, res13 } }, //===================================================================================== // Supported classes from the JPEGView Suite //===================================================================================== { // classes "image", cImage, "An image graphic", { // properties "", kAESpecialClassProperties, typeType, "", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural, "bounds", pBounds, cQDRectangle, "the boundary rectangle for the image", reserved, singleItem, notEnumerated, readWrite, res12, "comments", pComments, cIntlText, "the comments specified with the image", reserved, singleItem, notEnumerated, readOnly, res12, "display time", pDisplayTime, cLongInteger, "the time to decompress and display the image, in milliseconds", reserved, singleItem, notEnumerated, readOnly, res12, "format", pImageFormat, cType, "the file format of the image", reserved, singleItem, notEnumerated, readOnly, res12, "compression", pCompression, cType, "the type of compression used on the image", reserved, singleItem, notEnumerated, readOnly, res12, "has image colors", pHasImageColorTable, cBoolean, "Does the image have a color table?", reserved, singleItem, notEnumerated, readOnly, res12, "has reduced colors", pHasQuantColorTable, cBoolean, "Does the image have a reduced color table?", reserved, singleItem, notEnumerated, readOnly, res12, "image colors", pImageColorTable, cColorTable, "the imageÕs internal color table", reserved, singleItem, notEnumerated, readOnly, res12, "compressed", pIsCompressed, cBoolean, "Was the image compressed?", reserved, singleItem, notEnumerated, readOnly, res12, "aborted", pIsAborted, cBoolean, "Was the drawing of the image aborted?", reserved, singleItem, notEnumerated, readOnly, res12, "banded", pIsBanded, cBoolean, "Is the image banded?", reserved, singleItem, notEnumerated, readOnly, res12, "corrupt", pIsCorrupt, cBoolean, "Is the image corrupt?", reserved, singleItem, notEnumerated, readOnly, res12, "cropped", pIsCropped, cBoolean, "Is the image cropped?", reserved, singleItem, notEnumerated, readOnly, res12, "original bounds", pOriginalBounds, cQDRectangle, "the original bounds of the full image", reserved, singleItem, notEnumerated, readOnly, res12, "pixel depth", pPixelDepth, cShortInteger, "bits per pixel", reserved, singleItem, notEnumerated, readOnly, res12, "reduced colors", pQuantColorTable, cColorTable, "the imageÕs reduced color table", reserved, singleItem, notEnumerated, readOnly, res12, "length", pLength, cLongInteger, "the length of the image data, in bytes", reserved, singleItem, notEnumerated, readOnly, res12 }, { // elements cPixelMap, { formAbsolutePosition } }, "images", cImage, "Every image graphic", { // properties "", kAESpecialClassProperties, typeType, "", reserved, singleItem, notEnumerated, readOnly, res9, notFeminine, notMasculine, plural }, { }, "picture", 'PICT', "An image in PICT format", { }, // properties { }, // elements "JFIF", 'JPEG', "An image in JFIF format", { }, // properties { }, // elements "GIF", 'GIFf', "An image in GIF format", { }, // properties { }, // elements "startup screen", 'SCRN', "An image in startup screen format", { }, // properties { }, // elements "TIFF", 'TIFF', "An image in TIFF format", { }, // properties { }, // elements "BMP", 'BMPp', "An image in BMP format", { }, // properties { }, // elements "MacPaint", 'PNTG', "An image in MacPaint format", { }, // properties { }, // elements }, { }, // comparators { } // enumerators } }; \ No newline at end of file diff --git a/Source/68020/CopyFastScaledFrom32.a b/Source/68020/CopyFastScaledFrom32.a new file mode 100644 index 0000000..d8ec77e --- /dev/null +++ b/Source/68020/CopyFastScaledFrom32.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; srcBase = (long) pointer to the first source pixel ; srcRow = (long) rowBytes for the source pixmap ; dstBase = (long) pointer to the first destination pixel ; dstRow = (long) rowBytes for the destination pixmap ; itAddr = (long) pointer to the inverse color table ; ctAddr = (long) pointer to the color table ; theRgn = (long) handle to the destination region ; boxRect = (Rect) the bounding rectangle of this region ; height = (word) height of the region bounding box ; width = (word) width of the region bounding box ; srcWidth = (word) width of the source rectangle ; srcHeight = (word) height of the source rectangle ; dstWidth = (word) width of the destination rectangle ; dstHeight = (word) height of the destination rectangle ; xRemainder = (word) starting X remainder for the source counter ; yRemainder = (word) starting Y remainder for the source counter ; ; The following registers will be modified: ; ; d0,d1,d2 ; a0,a1 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = scratch register for expanding 24-bit pixels ; d2 = scratch [save for d6.l/d7.l] ; d3 = scratch [multiplier for xy-scale] ; d4 = (low word) remaining source Y pixels needed for current dest. Y ; d4 = (high word) dstHeight/srcHeight ; d5 = (low word) remaining Y fraction of current source pixel ; d5 = (high word) 1.00 ; d6 = (low word) remaining source Y pixels needed for current dest. X ; d6 = (high word) dstWidth/srcWidth ; d7 = (low word) remaining Y fraction of current source pixel ; d7 = (high word) scratch [save for d5.l] ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = sum of the red contributions ; a3 = sum of the green contributions ; a4 = sum of the blue contributions ; a5 = temporary save area for a0 ; movem.l d3-d7/a2-a6,-(sp) ;save registers on the stack move.l 48(sp),a6 ;get the address of the CopyData structure in a6 ;(based off stack: 10 registers + 1 a6 link + 1 return addr. ; = 12 * 4 bytes = 48 bytes) ; ; Create some room in the stack for our buffers ; clr.l d0 ;zero out d0 move.w width(a6),d0 ;get width of destination in d0.l addq.l #2,d0 ;plus two for overflows lsl.l #4,d0 ;times 16 (2 * 6 + 4) addq.l #4,d0 ;add 4 for alignment sub.l d0,sp ;get it from the stack space move.l d0,-(sp) ;and save the amount lsr.l #3,d0 ;return to times 2 move.l d0,d1 ;save that in d1 lsl.l #1,d0 ;d0 = width * 4 add.l d1,d0 ; = width * 6 moveq.l #13,d1 ;offset by 10, plus 3 for rounding up add.l sp,d1 ;add in the stack pointer andi.l #-4,d1 ;make it longword-aligned (-4 == $fffffffc) move.l d1,evenAddr(a6) ;that's the even buffer add.l d0,d1 ;point to the odd buffer move.l d1,oddAddr(a6) ;save that pointer add.l d0,d1 ;point to the scale buffer move.l d1,outputAddr(a6) ;now we've got them all ; ; Clear the dithering buffers to zeros ; move.l evenAddr(a6),a0 ;point to the evenBuffer subq.l #4,d1 ;decrement d1 for the dbra, plus the extras @ClearLoop: clr.w (a0)+ ;clear this word dbra.w d0,@ClearLoop ;loop for all dithering ; ; Initialize the region data ; move.l theRgn(a6),a0 ;get theRgn in a0 lea.l rgnBuffer(a6),a1 ;point a1 to the region buffer move.w boxRect+0(a6),d2 ;get box top in d2 move.w boxRect+2(a6),d3 ;box left in d3 move.w height(a6),d4 ;height in d4 move.w width(a6),d5 ;width in d5 jsr InitRegion ;initialize the region move.l a0,-(sp) ;store our pointer to the rgn on the stack ; ; Set up the source/destination quantities in the high words of d4-d7 ; clr.l d6 ;clear out d6 move.w dstHeight(a6),d6 ;get dest height there moveq.l #10,d0 ;get shift value in d0 lsl.l d0,d6 ;shift it up by 10 bits divu.w srcHeight(a6),d6 ;divide by source height addq.w #1,d6 ;plus one to prevent overflows swap d6 ;swap it high clr.l d4 ;clear out d4 move.w dstWidth(a6),d4 ;get destination width in d4 lsl.l d0,d4 ;shift d6 up by 10 bits divu.w srcWidth(a6),d4 ;divide by source width addq.w #1,d4 ;plus one to prevent overflows swap d4 ;into high word of d6 ; ; Set up the counter "rows" & reset the source Y remainder ; move.w height(a6),rows(a6) ;set up the row counter move.w yRemainder(a6),d5 ;restore yRemainder ; ; The outermost (row) loop begins here; set up our pointers into the data ; @ScaleRowLoop: move.l srcBase(a6),a0 ;get pointer to source in a0 move.l outputAddr(a6),a1 ;put to destination with a1 ; ; Reset the "columns" counter and reset the source X remainder ; move.w width(a6),columns(a6);reset the column counter move.w xRemainder(a6),d7 ;restore xRemainder move.w #512,d3 ;set up our threshhold (512 == $200) ; ; The inner (column) loop begins here; set up our counters in the destination system ; @ScaleColLoop: move.w #1024,d6 ;initialize our X counter (1024 == $400) move.w d6,d4 ;initialize our Y counter ; ; Determine what sort of scaling is best for us ; cmp.w d4,d5 ;can we avoid Y scaling? bge.s @NoYScale ;if so, check X as well cmp.w d6,d7 ;can we at least avoid X scaling? blt.w @ScaleXY ;if not, scale in both bra.w @ScaleY ;otherwise, scale in Y only @NoYScale: cmp.w d6,d7 ;do we have to scale in X? bge.w @NoScale ;if not, do it quick bra.w @ScaleX ;otherwise, just scale X ; ; Special case "divides": table lookups <= 8, 1 or 0 ; @ScaleColFast: addq.w #5,d2 ;restore divisor back to 0-5 lea sTable(a6),a4 ;point a4 to the table move.l 0(a4,d2.w*4),a4 ;look up the longword address clr.l d1 ;zero out the accumulator move.l a2,d0 ;get red/blue into d0 move.b 0(a4,d0.w),d1 ;get the red part lsl.l #8,d1 ;shift it up 8 bits swap d2 ;put green dividend low move.b 0(a4,d2.w),d1 ;get the green part lsl.l #8,d1 ;shift it up 8 bits swap d0 ;put blue dividend low move.b 0(a4,d0.w),d1 ;get the blue part move.l d1,(a1)+ ;store it in memory bra.s @ScaleColSkip ;skip back to the main loop @ScaleCol210: addq.w #1,d2 ;add 1 back bne.s @ScaleCol10 ;if not zero now, try for 1 swap d2 ;swap d2's words lsr.w #1,d2 ;divide by 2 move.l a2,d1 ;get red/blue parts swap d1 ;swap them into the right order lsr.l #1,d1 ;shift those down by 1 bit ror.l #8,d1 ;rotate down 8 bits move.b d2,d1 ;copy in the green rol.l #8,d1 ;rotate back move.l d1,(a1)+ ;copy that bra.s @ScaleColSkip ;skip back to the main loop @ScaleCol10: addq.w #1,d2 ;add 1 back bne.s @ScaleColCopy ;if not zero now, must be 0 swap d2 ;swap d2's words lsl.w #8,d2 ;shift it up 8 bits move.l a2,d1 ;get red/blue parts swap d1 ;swap them into the right order or.w d2,d1 ;or the green into them move.l d1,(a1)+ ;copy that bra.s @ScaleColSkip ;skip back to the main loop @ScaleColCopy: move.l (a0),(a1)+ ;just copy last pixel bra.s @ScaleColSkip ;skip back to main loop ; ; End of the columns loop here; decrement counters and loop until done ; @ScaleColEnd: move.l a3,d2 ;get a3 into d2 subq.w #3,d2 ;subtract off 3 bmi.s @ScaleCol210 ;if negative, either 2, 1 or 0 pixels subq.w #5,d2 ;subtract off 5 more ble.s @ScaleColFast ;if negative, do table look-up addq.w #8,d2 ;otherwise, restore our divisor move.l d2,d0 ;copy d2 to d0 clr.w d0 ;clear out the divisor swap d0 ;get the green part low divu.w d2,d0 ;divide by d2 clr.l d1 ;clear out d1 for storage lsl.l #8,d0 ;shift green into place move.w d0,d1 ;move it into d1 move.l a2,d0 ;get red/blue into d0 clr.w d0 ;zero out red part swap d0 ;swap blue down divu.w d2,d0 ;divide by d2 move.b d0,d1 ;store low-order byte move.l a2,d0 ;get red/blue again in d0 swap d0 ;swap halves clr.w d0 ;clear out the blue swap d0 ;swap red back divu.w d2,d0 ;divide by d2 swap d0 ;swap it back high clr.w d0 ;zero the remainder or.l d0,d1 ;or into the final result move.l d1,(a1)+ ;store it in memory @ScaleColSkip: subq.w #1,columns(a6) ;decrement columns bne.w @ScaleColLoop ;loop if not done ; ; We now have a row; save our registers and set up to do a dithered copy ; movem.l d4-d7,-(sp) ;save registers move.l outputAddr(a6),a0 ;source here move.l dstBase(a6),a1 ;get destination address move.l itAddr(a6),a2 ;inverse color table move.l ctAddr(a6),a3 ;color table lea.l rgnBuffer+4(a6),a4 ;get rgnBuffer address in a4 move.l a4,d2 ;point d2 (a6) to the region buffer move.l evenAddr(a6),d0 ;even address move.l oddAddr(a6),d1 ;odd address move.l errTable(a6),d6 ;point d6 to the error table move.w width(a6),d7 ;column count bchg.b #0,evodd+1(a6) ;check the even/odd flag beq.s @ScaleEven ;if zero, do an even row move.l odd(a6),a4 ;get address of routine jsr (a4) ;otherwise, dither as an odd row bra.s @ScaleRowEnd ;skip ahead @ScaleEven: move.l even(a6),a4 ;get address of routine jsr (a4) ;dither as an even row @ScaleRowEnd: movem.l (sp)+,d4-d7 ;restore registers ; ; Adjust ourselves for the next row ; subq.w #1,rows(a6) ;decrement rows beq.w @ScaleExit ;exit if done move.l dstRow(a6),d0 ;get destination row increment in d0 add.l d0,dstBase(a6) ;point to next destination row move.l srcRow(a6),d0 ;get source row increment in d0 move.w #1024,d4 ;get 1.00 count in d4 (1024 == $400) swap d6 ;swap d6 beforehand for speed @ScaleIncRow: cmp.w d4,d5 ;did we upgrade 1 row? bgt.s @ScaleRowNext ;if not, loop add.l d0,srcBase(a6) ;point to next source row sub.w d5,d4 ;adjust Y for remainder move.w d6,d5 ;reset Y count for the new pixel bra.s @ScaleIncRow ;handle any further adjustments @ScaleRowNext: swap d6 ;restore d6 sub.w d4,d5 ;get the new Y multiplier ; ; Update the region counters ; subq.w #1,rgnBuffer(a6) ;decrement the Y region count bne.w @ScaleRowLoop ;skip if we're not done move.l (sp)+,a0 ;restore region pointer lea.l rgnBuffer+4(a6),a1 ;point a1 into the region buffer move.w boxRect+2(a6),d0 ;get left end of the box in d0 jsr UpdateRegion ;update our region move.l a0,-(sp) ;push new position again bra.w @ScaleRowLoop ;loop for more ;------------------------- NoScale --------------------------- @NoScale: move.l (a0),(a1)+ ;just copy src->dest sub.w d6,d7 ;adjust for remainder bra.w @ScaleColSkip ;loop for another ;------------------------- ScaleX ---------------------------- @ScaleX: clr.l d0 ;clear out d0 move.l d0,a2 ;zero out the colors: red/blue move.l d0,a3 ;green/counter swap d4 ;swap our update to X low here cmp.w d3,d7 ;are we below the lower threshhold? blt.s @SXSkip1 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXSkip1: addq.l #4,a0 ;point to the next pixel sub.w d7,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? bgt.s @SXSkip2 ;if not, skip @SXLoop2: move.l (a0)+,d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count add.l d0,a2 ;add again: red/blue add.l d1,a3 ;green/count sub.w d4,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? ble.s @SXLoop2 ;if so, loop again @SXSkip2: cmp.w d3,d6 ;are we below the lower threshhold? blt.s @SXSkip3 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXSkip3: move.w d4,d7 ;set up source remainder sub.w d6,d7 ;adjust it swap d4 ;swap d4 back bra.w @ScaleColEnd ;loop for the next pixel ;------------------------- ScaleY ---------------------------- @ScaleY: clr.l d0 ;clear out d0 move.l d0,a2 ;zero out the colors: red/blue move.l d0,a3 ;green/counter swap d6 ;swap our update to Y low here move.l a0,a4 ;copy a0 into a4 for storage move.l srcRow(a6),d2 ;get source row into d2 for speed swap d7 ;swap d7 high move.w d5,d7 ;save d5 into high word swap d7 ;restore d7 now cmp.w d3,d5 ;are we below the lower threshhold? blt.s @SYSkip1 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SYSkip1: add.l d2,a0 ;point to the next row sub.w d5,d4 ;adjust Y for remainder cmp.w d4,d6 ;do we have a whole pixel to add? bgt.s @SYSkip2 ;if not, skip @SYLoop2: move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count add.l d2,a0 ;point to the next row sub.w d6,d4 ;adjust Y for remainder cmp.w d4,d6 ;do we have a whole pixel to add? ble.s @SYLoop2 ;if not, skip @SYSkip2: cmp.w d3,d4 ;are we below the lower threshhold? blt.s @SYSkip3 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SYSkip3: move.w d6,d5 ;reset the source remainder sub.w d4,d5 ;adjust Y for remainder swap d6 ;swap d6 back swap d7 ;swap d7 high move.w d7,d5 ;restore original d5 here swap d7 ;restore d7 move.l a4,a0 ;restore original a0 here sub.w d6,d7 ;adjust X for remainder bra.w @ScaleColEnd ;loop for the next pixel ;------------------------- ScaleXY ---------------------------- @ScaleXY: clr.l d0 ;clear out d0 move.l d0,a2 ;zero out the colors: red/blue move.l d0,a3 ;green/counter move.l a0,a5 ;save a0 in a5 swap d7 ;swap d7 move.w d5,d7 ;save d5.l there swap d7 ;safely in the high word move.w d7,d2 ;save d7 in d2 ; ; Handle Y section 1 ; cmp.w d3,d5 ;are we below the lower threshhold in Y? blt.s @SXYSkipY1 ;if so, skip entirely move.l a0,a4 ;copy a0 to a4 for now swap d4 ;swap d4 low for fast access cmp.w d3,d7 ;are we below the lower threshhold in X? blt.s @SXYSkipY1X1 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXYSkipY1X1: addq.l #4,a0 ;point to the next pixel sub.w d7,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? bgt.s @SXYSkipY1X2 ;if not, skip @SXYLoopY1X2: move.l (a0)+,d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count sub.w d4,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? ble.s @SXYLoopY1X2 ;if so, loop again @SXYSkipY1X2: cmp.w d3,d6 ;are we below the lower threshhold? blt.s @SXYSkipY1X3 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXYSkipY1X3: swap d4 ;swap d4 back move.w #1024,d6 ;restore source counter in d6 (1024 == $400) move.w d2,d7 ;restore source remainder in d7 movea.l a4,a0 ;restore a0 @SXYSkipY1: add.l srcRow(a6),a0 ;point to the next row sub.w d5,d4 ;adjust Y for remainder ; ; Handle Y section 2 ; swap d6 ;get src pixel contribution in d6 cmp.w d4,d6 ;still another whole pixel in Y to go? bgt.s @SXYSkipY2 ;if not, skip over this section @SXYLoopY2: swap d6 ;swap d6 back move.l a0,a4 ;copy a0 to a4 for now swap d4 ;swap d4 low for fast access cmp.w d3,d7 ;are we below the lower threshhold in X? blt.s @SXYSkipY2X1 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXYSkipY2X1: addq.l #4,a0 ;point to the next pixel sub.w d7,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? bgt.s @SXYSkipY2X2 ;if not, skip @SXYLoopY2X2: move.l (a0)+,d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count add.l d0,a2 ;add again: red/blue add.l d1,a3 ;green/count sub.w d4,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? ble.s @SXYLoopY2X2 ;if so, loop again @SXYSkipY2X2: cmp.w d3,d6 ;are we below the lower threshhold? blt.s @SXYSkipY2X3 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXYSkipY2X3: swap d4 ;swap d4 back move.w #1024,d6 ;restore source counter in d6 (1024 == $400) move.w d2,d7 ;restore source remainder in d7 movea.l a4,a0 ;restore a0 add.l srcRow(a6),a0 ;point to the next row swap d6 ;get src pixel contribution in d6 sub.w d6,d4 ;adjust Y for remainder cmp.w d4,d6 ;still another whole pixel in Y to go? ble.s @SXYLoopY2 ;if so, loop for more @SXYSkipY2: swap d6 ;put d6 back to normal ; ; Handle Y section 3 ; sub.l a0,a5 ;subtract current a0 from original in a5 swap d4 ;swap d4 low for fast access cmp.w d3,d4 ;are we below the lower threshhold in Y? blt.s @SXYSkipY3 ;if so, skip entirely cmp.w d3,d7 ;are we below the lower threshhold in X? blt.s @SXYSkipY3X1 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXYSkipY3X1: addq.l #4,a0 ;point to the next pixel sub.w d7,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? bgt.s @SXYSkipY3X2 ;if not, skip @SXYLoopY3X2: move.l (a0)+,d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count sub.w d4,d6 ;adjust the counter cmp.w d6,d4 ;do we include a whole pixel now? ble.s @SXYLoopY3X2 ;if so, loop again @SXYSkipY3X2: cmp.w d3,d6 ;are we below the lower threshhold? blt.s @SXYSkipY3X3 ;if so, skip entirely move.l (a0),d1 ;get next pixel swap d1 ;swap halves move.l d1,d0 ;copy into d0 lsr.l #8,d1 ;shift green part into bits 16-23 andi.l #16711935,d0 ;isolate red/blue parts in d0 (16711935 == $ff00ff) move.w #1,d1 ;put a 1 in d1's lower word add.l d0,a2 ;add into totals: red/blue add.l d1,a3 ;green/count @SXYSkipY3X3: @SXYContinue: move.w d4,d7 ;restore X source fraction swap d4 ;swap d4 back sub.w d6,d7 ;adjust X for remainder swap d7 ;swap d7's words move.w d7,d5 ;restore d5 swap d7 ;put things back adda.l a5,a0 ;point back to original row bra.w @ScaleColEnd ;scale the values & loop @SXYSkipY3: addq.l #4,a0 ;point to the next pixel sub.w d7,d6 ;adjust the counter @SXYLoopY3: cmp.w d6,d4 ;do we include a whole pixel now? bgt.s @SXYContinue ;if not, skip addq.l #4,a0 ;point to the next pixel sub.w d4,d6 ;adjust the counter bra.s @SXYLoopY3 ;loop for more @ScaleExit: add.l #4,sp ;pop off region position move.l (sp)+,d0 ;get length of buffer add.l d0,sp ;get it off the stack movem.l (sp)+,d3-d7/a2-a6 ;get registers from the stack \ No newline at end of file diff --git a/Source/68020/CopyReallyFastScaledFrom32.a b/Source/68020/CopyReallyFastScaledFrom32.a new file mode 100644 index 0000000..5416fcd --- /dev/null +++ b/Source/68020/CopyReallyFastScaledFrom32.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; srcBase = (long) pointer to the first source pixel ; srcRow = (long) rowBytes for the source pixmap ; dstBase = (long) pointer to the first destination pixel ; dstRow = (long) rowBytes for the destination pixmap ; itAddr = (long) pointer to the inverse color table ; ctAddr = (long) pointer to the color table ; theRgn = (long) handle to the destination region ; boxRect = (Rect) the bounding rectangle of this region ; height = (word) height of the region bounding box ; width = (word) width of the region bounding box ; srcWidth = (word) width of the source rectangle ; srcHeight = (word) height of the source rectangle ; dstWidth = (word) width of the destination rectangle ; dstHeight = (word) height of the destination rectangle ; xRemainder = (word) starting X remainder for the source counter ; yRemainder = (word) starting Y remainder for the source counter ; ; The following registers will be modified: ; ; d0,d1,d2 ; a0,a1 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = scratch register for expanding 24-bit pixels ; d2 = scratch [save for d6.l/d7.l] ; d3 = scratch [multiplier for xy-scale] ; d4 = (low word) remaining source Y pixels needed for current dest. Y ; d4 = (high word) dstHeight/srcHeight ; d5 = (low word) remaining Y fraction of current source pixel ; d5 = (high word) 1.00 ; d6 = (low word) remaining source Y pixels needed for current dest. X ; d6 = (high word) dstWidth/srcWidth ; d7 = (low word) remaining Y fraction of current source pixel ; d7 = (high word) scratch [save for d5.l] ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = sum of the red contributions ; a3 = sum of the green contributions ; a4 = sum of the blue contributions ; a5 = temporary save area for a0 ; movem.l d3-d7/a2-a6,-(sp) ;save registers on the stack move.l 48(sp),a6 ;get the address of the CopyData structure in a6 ;(based off stack: 10 registers + 1 a6 link + 1 return addr. ; = 12 * 4 bytes = 48 bytes) ; ; Create some room in the stack for our buffers ; clr.l d0 ;zero out d0 move.w width(a6),d0 ;get width of destination in d0.l addq.l #2,d0 ;plus two for overflows lsl.l #4,d0 ;times 16 (2 * 6 + 4) addq.l #4,d0 ;add 4 for alignment sub.l d0,sp ;get it from the stack space move.l d0,-(sp) ;and save the amount lsr.l #3,d0 ;return to times 2 move.l d0,d1 ;save that in d1 lsl.l #1,d0 ;d0 = width * 4 add.l d1,d0 ; = width * 6 moveq.l #13,d1 ;offset by 10, plus 3 for rounding up add.l sp,d1 ;add in the stack pointer andi.l #-4,d1 ;make it longword-aligned (-4 == $fffffffc) move.l d1,evenAddr(a6) ;that's the even buffer add.l d0,d1 ;point to the odd buffer move.l d1,oddAddr(a6) ;save that pointer add.l d0,d1 ;point to the scale buffer move.l d1,outputAddr(a6) ;now we've got them all ; ; Clear the dithering buffers to zeros ; move.l oddAddr(a6),a0 ;point to the odd buffer by default subq.l #4,d1 ;decrement d1 for the dbra, plus the extras lsr.l #1,d0 ;divide by two since we only clear one buffer btst.b #0,evodd+1(a6) ;check the even/odd flag bne.s @ClearLoop ;if even, skip ahead move.l evenAddr(a6),a0 ;point to the even buffer @ClearLoop: clr.w (a0)+ ;clear this word dbra.w d0,@ClearLoop ;loop for all dithering ; ; Initialize the region data ; move.l theRgn(a6),a0 ;get theRgn in a0 lea.l rgnBuffer(a6),a1 ;point a1 to the region buffer move.w boxRect+0(a6),d2 ;get box top in d2 move.w boxRect+2(a6),d3 ;box left in d3 move.w height(a6),d4 ;height in d4 move.w width(a6),d5 ;width in d5 jsr InitRegion ;initialize the region move.l a0,-(sp) ;store our pointer to the rgn on the stack ; ; Set up the source/destination quantities in the high words of d4-d7 ; clr.l d6 ;clear out d6 move.w dstHeight(a6),d6 ;get dest height there moveq.l #10,d0 ;get shift value in d0 lsl.l d0,d6 ;shift it up by 10 bits divu.w srcHeight(a6),d6 ;divide by source height addq.w #1,d6 ;plus one to prevent overflows swap d6 ;swap it high clr.l d4 ;clear out d4 move.w dstWidth(a6),d4 ;get destination width in d4 lsl.l d0,d4 ;shift d6 up by 10 bits divu.w srcWidth(a6),d4 ;divide by source width addq.w #1,d4 ;plus one to prevent overflows swap d4 ;into high word of d6 ; ; Set up the counter "rows" & reset the source Y remainder ; move.w height(a6),rows(a6) ;set up the row counter move.w yRemainder(a6),d5 ;restore yRemainder ; ; The outermost (row) loop begins here; set up our pointers into the data ; @ScaleRowLoop: move.l srcBase(a6),a0 ;get pointer to source in a0 move.l outputAddr(a6),a1 ;put to destination with a1 ; ; Reset the "columns" counter and reset the source X remainder ; move.w width(a6),columns(a6);reset the column counter move.w xRemainder(a6),d7 ;restore xRemainder ; ; The inner (column) loop begins here; find starting pixel location in Y ; move.w #1024,d0 ;get needed Y in d0 cmp.w d0,d5 ;is the Y contribution completely contained? bgt.s @ScaleCommon ;if so, go straight to the common scaling sub.w d5,d0 ;subtract off remaining source swap d6 ;get source Y contribution in d6 cmp.w d0,d6 ;do we overlap next Y pixel only? ble.s @NotScaleY2 ;if not, skip ahead swap d6 ;swap d6 back cmp.w d0,d5 ;should we skip ahead a row? bgt.s @ScaleCommon ;if not, go ahead and go for it add.w srcRow(a6),a0 ;point to the next row bra.s @ScaleCommon ;and *then* go for it @NotScaleY2: swap d6 ;swap d6 back add.w srcRow(a6),a0 ;point to the next row ; ; The common scaling loop; here we copy pixels from the current row to the destination ; @ScaleCommon: swap d4 ;get the X contribution @ScaleColLoop: move.w #1024,d6 ;initialize our X counter (1024 == $400) cmp.w d6,d7 ;is the X contribution completely contained? ble.s @ScaleX1 ;if not, skip this move.l (a0),(a1)+ ;copy the current source pixel bra.s @ScaleEnd ;skip to the end @ScaleX1: sub.w d7,d6 ;subtract remaining X from our needed X cmp.w d6,d4 ;do we overlap onto next pixel only? ble.s @ScaleX2 ;if not, skip cmp.w d6,d7 ;which pixel do we contribute? ble.s @ScaleX1Add2 ;if second one, skip ahead move.l (a0)+,(a1)+ ;copy the first pixel and increment bra.s @ScaleEndReset ;skip to the end @ScaleX1Add2: addq.l #4,a0 ;increment source first move.l (a0),(a1)+ ;copy second pixel now bra.s @ScaleEndReset ;skip to the end @ScaleX2: addq.l #4,a0 ;increment source move.l (a0)+,(a1)+ ;copy second pixel and increment @ScaleX2Loop: sub.w d4,d6 ;subtract contribution cmp.w d6,d4 ;see if we have another whole contribution left bgt.s @ScaleEndReset ;if not, reset the needed value addq.l #4,a0 ;increment source bra.s @ScaleX2Loop ;loop until we exit @ScaleEndReset: move.w d4,d7 ;set the needed value to the contribution @ScaleEnd: sub.w d6,d7 ;subtract needed from remaining subq.w #1,columns(a6) ;decrement the columns count bne.s @ScaleColLoop ;loop until done ; ; We now have a row; save our registers and set up to do a dithered copy ; swap d4 ;swap d4 back movem.l d4-d7,-(sp) ;save registers move.l outputAddr(a6),a0 ;source here move.l dstBase(a6),a1 ;get destination address move.l itAddr(a6),a2 ;inverse color table move.l ctAddr(a6),a3 ;color table lea.l rgnBuffer+4(a6),a4 ;get rgnBuffer address in a4 move.l a4,d2 ;point d2 (a6) to the region buffer move.l evenAddr(a6),d0 ;even address move.l oddAddr(a6),d1 ;odd address move.l errTable(a6),d6 ;point d6 to the error table move.w width(a6),d7 ;column count bchg.b #0,evodd+1(a6) ;check the even/odd flag beq.s @ScaleEven ;if zero, do an even row move.l odd(a6),a4 ;get address of routine jsr (a4) ;otherwise, dither as an odd row bra.s @ScaleRowEnd ;skip ahead @ScaleEven: move.l even(a6),a4 ;get address of routine jsr (a4) ;dither as an even row @ScaleRowEnd: movem.l (sp)+,d4-d7 ;restore registers ; ; Adjust ourselves for the next row ; subq.w #1,rows(a6) ;decrement rows beq.s @ScaleExit ;exit if done move.l dstRow(a6),d0 ;get destination row increment in d0 add.l d0,dstBase(a6) ;point to next destination row move.l srcRow(a6),d0 ;get source row increment in d0 move.w #1024,d4 ;get 1.00 count in d4 (1024 == $400) swap d6 ;swap d6 beforehand for speed @ScaleIncRow: cmp.w d4,d5 ;did we upgrade 1 row? bgt.s @ScaleRowNext ;if not, loop add.l d0,srcBase(a6) ;point to next source row sub.w d5,d4 ;adjust Y for remainder move.w d6,d5 ;reset Y count for the new pixel bra.s @ScaleIncRow ;handle any further adjustments @ScaleRowNext: swap d6 ;restore d6 sub.w d4,d5 ;get the new Y multiplier ; ; Update the region counters ; subq.w #1,rgnBuffer(a6) ;decrement the Y region count bne.w @ScaleRowLoop ;skip if we're not done move.l (sp)+,a0 ;restore region pointer lea.l rgnBuffer+4(a6),a1 ;point a1 into the region buffer move.w boxRect+2(a6),d0 ;get left end of the box in d0 jsr UpdateRegion ;update our region move.l a0,-(sp) ;push new position again bra.w @ScaleRowLoop ;loop for more @ScaleExit: add.l #4,sp ;pop off region position move.l (sp)+,d0 ;get length of buffer add.l d0,sp ;get it off the stack movem.l (sp)+,d3-d7/a2-a6 ;get registers from the stack \ No newline at end of file diff --git a/Source/68020/CopyScaledFrom32.a b/Source/68020/CopyScaledFrom32.a new file mode 100644 index 0000000..0c2cf45 --- /dev/null +++ b/Source/68020/CopyScaledFrom32.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; srcBase = (long) pointer to the first source pixel ; srcRow = (long) rowBytes for the source pixmap ; dstBase = (long) pointer to the first destination pixel ; dstRow = (long) rowBytes for the destination pixmap ; itAddr = (long) pointer to the inverse color table ; ctAddr = (long) pointer to the color table ; theRgn = (long) handle to the destination region ; boxRect = (Rect) the bounding rectangle of this region ; height = (word) height of the region bounding box ; width = (word) width of the region bounding box ; srcWidth = (word) width of the source rectangle ; srcHeight = (word) height of the source rectangle ; dstWidth = (word) width of the destination rectangle ; dstHeight = (word) height of the destination rectangle ; xRemainder = (word) starting X remainder for the source counter ; yRemainder = (word) starting Y remainder for the source counter ; ; The following registers will be modified: ; ; d0,d1,d2 ; a0,a1 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = scratch register for expanding 24-bit pixels ; d2 = scratch [save for d6.l/d7.l] ; d3 = scratch [multiplier for xy-scale] ; d4 = (low word) remaining source Y pixels needed for current dest. Y ; d4 = (high word) dstHeight/srcHeight ; d5 = (low word) remaining Y fraction of current source pixel ; d5 = (high word) 1.00 ; d6 = (low word) remaining source Y pixels needed for current dest. X ; d6 = (high word) dstWidth/srcWidth ; d7 = (low word) remaining Y fraction of current source pixel ; d7 = (high word) scratch [save for d5.l] ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = sum of the red contributions ; a3 = sum of the green contributions ; a4 = sum of the blue contributions ; a5 = temporary save area for a0 ; movem.l d3-d7/a2-a6,-(sp) ;save registers on the stack move.l 48(sp),a6 ;get the address of the CopyData structure in a6 ;(based off stack: 10 registers + 1 a6 link + 1 return addr. ; = 12 * 4 bytes = 48 bytes) ; ; Create some room in the stack for our buffers ; clr.l d0 ;zero out d0 move.w width(a6),d0 ;get width of destination in d0.l addq.l #2,d0 ;plus two for overflows lsl.l #4,d0 ;times 16 (2 * 6 + 4) addq.l #4,d0 ;add 4 for alignment sub.l d0,sp ;get it from the stack space move.l d0,-(sp) ;and save the amount lsr.l #3,d0 ;return to times 2 move.l d0,d1 ;save that in d1 lsl.l #1,d0 ;d0 = width * 4 add.l d1,d0 ; = width * 6 moveq.l #13,d1 ;offset by 10, plus 3 for rounding up add.l sp,d1 ;add in the stack pointer andi.l #-4,d1 ;make it longword-aligned (-4 == $fffffffc) move.l d1,evenAddr(a6) ;that's the even buffer add.l d0,d1 ;point to the odd buffer move.l d1,oddAddr(a6) ;save that pointer add.l d0,d1 ;point to the scale buffer move.l d1,outputAddr(a6) ;now we've got them all ; ; Clear the dithering buffers to zeros ; move.l evenAddr(a6),a0 ;point to the evenBuffer subq.l #4,d1 ;decrement d1 for the dbra, plus the extras @ClearLoop: clr.w (a0)+ ;clear this word dbra.w d0,@ClearLoop ;loop for all dithering ; ; Initialize the region data ; move.l theRgn(a6),a0 ;get theRgn in a0 lea.l rgnBuffer(a6),a1 ;point a1 to the region buffer move.w boxRect+0(a6),d2 ;get box top in d2 move.w boxRect+2(a6),d3 ;box left in d3 move.w height(a6),d4 ;height in d4 move.w width(a6),d5 ;width in d5 jsr InitRegion ;initialize the region move.l a0,-(sp) ;store our pointer to the rgn on the stack ; ; Set up the source/destination quantities in the high words of d4-d7 ; move.w #1024,d5 ;get 1.00 into d5 (1024 == $0400) swap d5 ;swap it high clr.l d4 ;clear out d4 move.w dstHeight(a6),d4 ;get dest height there moveq.l #10,d0 ;get shift value in d0 lsl.l d0,d4 ;shift it up by 10 bits move.w srcHeight(a6),d0 ;get source height in d0 divu.w d0,d4 ;divide by full source height addq.w #1,d4 ;plus one to prevent overflows swap d4 ;swap it high clr.l d6 ;clear out d6 move.w dstWidth(a6),d6 ;get destination width in d6 moveq.l #10,d0 ;get shift value in d0 lsl.l d0,d6 ;shift d6 up by 10 bits move.w srcWidth(a6),d0 ;get source width in d0 divu.w d0,d6 ;divide by full source width addq.w #1,d4 ;plus one to prevent overflows swap d6 ;into high word of d6 ; ; Set up the counter "rows" & reset the source Y remainder ; move.w height(a6),rows(a6) ;set up the row counter move.w yRemainder(a6),d5 ;restore yRemainder ; ; The outermost (row) loop begins here; set up our pointers into the data ; @ScaleRowLoop: move.l srcBase(a6),a0 ;get pointer to source in a0 move.l outputAddr(a6),a1 ;put to destination with a1 ; ; Reset the "columns" counter and reset the source X remainder ; move.w width(a6),columns(a6);reset the column counter move.w xRemainder(a6),d7 ;restore xRemainder ; ; The inner (column) loop begins here; set up our counters in the destination system ; @ScaleColLoop: swap d5 ;reset remaining destination to 1.00 move.w d5,d4 ;first in X move.w d5,d6 ;and then in Y swap d5 ;restore d5 clr.l d0 ;clear out d0 move.l d0,a2 ;zero out the colors: red move.l d0,a3 ;green move.l d0,a4 ;blue ; ; Determine what sort of scaling is best for us ; cmp.w d4,d5 ;can we avoid Y scaling? bge.s @NoYScale ;if so, check X as well cmp.w d6,d7 ;can we at least avoid X scaling? bge.w @ScaleY ;if so, scale in Y only bra.w @ScaleXY ;otherwise, scale in both @NoYScale: cmp.w d6,d7 ;do we have to scale in X? bge.w @NoScale ;if not, do it quick bra.w @ScaleX ;otherwise, just scale X ; ; End of the columns loop here; decrement counters and loop until done ; @ScaleColEnd: move.l a2,d1 ;get red in d1 lsl.l #6,d1 ;shift it up six bits here move.l a3,d0 ;get green in d0 lsr.l #2,d0 ;shift it down two bits move.w d0,d1 ;copy the resulting word in move.l a4,d0 ;get blue in d0 moveq.l #10,d2 ;get shift amount in d2 lsr.l d2,d0 ;shift it down ten bits move.b d0,d1 ;copy the last byte in move.l d1,(a1)+ ;store that to the output @ScaleColSkip: subq.w #1,columns(a6) ;decrement columns bne.s @ScaleColLoop ;loop if not done ; ; We now have a row; save our registers and set up to do a dithered copy ; movem.l d4-d7,-(sp) ;save registers move.l outputAddr(a6),a0 ;source here move.l dstBase(a6),a1 ;get destination address move.l itAddr(a6),a2 ;inverse color table move.l ctAddr(a6),a3 ;color table lea.l rgnBuffer+4(a6),a4 ;get rgnBuffer address in a4 move.l a4,d2 ;point d2 (a6) to the region buffer move.l evenAddr(a6),d0 ;even address move.l oddAddr(a6),d1 ;odd address move.l errTable(a6),d6 ;point d6 to the error table move.w width(a6),d7 ;column count bchg.b #0,evodd+1(a6) ;check the even/odd flag beq.s @ScaleEven ;if zero, do an even row move.l odd(a6),a4 ;get address of routine jsr (a4) ;otherwise, dither as an odd row bra.s @ScaleRowEnd ;skip ahead @ScaleEven: move.l even(a6),a4 ;get address of routine jsr (a4) ;dither as an even row @ScaleRowEnd: movem.l (sp)+,d4-d7 ;restore registers ; ; Adjust ourselves for the next row ; subq.w #1,rows(a6) ;decrement rows beq.w @ScaleExit ;exit if done move.l dstRow(a6),d0 ;get destination row increment in d0 add.l d0,dstBase(a6) ;point to next destination row move.l srcRow(a6),d0 ;get source row increment in d0 swap d5 ;swap d5 low move.w d5,d4 ;get 1.00 count in d4 swap d5 ;restore d5 @ScaleIncRow: cmp.w d4,d5 ;did we upgrade 1 row? bgt.s @ScaleRowNext ;if not, loop add.l d0,srcBase(a6) ;point to next source row sub.w d5,d4 ;adjust Y for remainder swap d4 ;get destination height in d4 move.w d4,d5 ;reset Y count for the new pixel swap d4 ;restore Y count bra.s @ScaleIncRow ;handle any further adjustments @ScaleRowNext: sub.w d4,d5 ;get the new Y multiplier ; ; Update the region counters ; subq.w #1,rgnBuffer(a6) ;decrement the Y region count bne.w @ScaleRowLoop ;skip if we're not done move.l (sp)+,a0 ;restore region pointer lea.l rgnBuffer+4(a6),a1 ;point a1 into the region buffer move.w boxRect+2(a6),d0 ;get left end of the box in d0 jsr UpdateRegion ;update our region move.l a0,-(sp) ;push new position again bra.w @ScaleRowLoop ;loop for more ;------------------------- NoScale --------------------------- @NoScale: move.l (a0),(a1)+ ;just copy src->dest sub.w d6,d7 ;adjust for remainder bne.s @NSR ;skip this if not done in X here swap d6 ;get source fraction in d6 move.w d6,d7 ;reset d7 to a new value swap d6 ;restore d6 addq.l #4,a0 ;point to next pixel @NSR: bra.w @ScaleColSkip ;loop for another ;------------------------- ScaleX ---------------------------- @ScaleX: move.l (a0)+,d1 ;get the next pixel clr.l d0 ;clear out d0 move.b d1,d0 ;get the blue into d0 mulu.w d7,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d7,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d7,d0 ;times remainder of the source add.l d0,a2 ;add to the red total sub.w d7,d6 ;adjust X for remainder swap d6 ;get dest width in d6 move.w d6,d7 ;reset X count for the new pixel swap d6 ;restore X count cmp.w d6,d7 ;still another whole pixel to go? blt.s @ScaleX ;if so, loop again move.l (a0),d1 ;get the next pixel clr.l d0 ;clear out d0 move.b d1,d0 ;get the blue into d0 mulu.w d6,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d6,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d6,d0 ;times remainder of the source add.l d0,a2 ;add to the red total sub.w d6,d7 ;adjust X for remainder bne.w @ScaleColEnd ;if we don't need next pixel, skip swap d6 ;get dest. width in d6 move.w d6,d7 ;reset X counter for new pixel swap d6 ;restore X counter addq.l #4,a0 ;point to it in memory bra.w @ScaleColEnd ;loop for the next pixel ;------------------------- ScaleY ---------------------------- @ScaleY: move.l a0,a5 ;copy a0 into a5 for storage move.l srcRow(a6),d2 ;get source row into d2 for speed move.w d5,d3 ;save d5 into d3 @ScaleYLoop: move.l (a0),d1 ;get the next pixel clr.l d0 ;clear out d0 move.b d1,d0 ;get the blue into d0 mulu.w d5,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d5,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d5,d0 ;times remainder of the source add.l d0,a2 ;add to the red total add.l d2,a0 ;point to the next row sub.w d5,d4 ;adjust Y for remainder swap d4 ;get destination height in d4 move.w d4,d5 ;reset Y count for the new pixel swap d4 ;restore Y count cmp.w d4,d5 ;still another whole pixel to go? blt.s @ScaleYLoop ;if so, loop again move.l (a0),d1 ;get the next pixel clr.l d0 ;clear out d0 move.b d1,d0 ;get the blue into d0 mulu.w d4,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d4,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d4,d0 ;times remainder of the source add.l d0,a2 ;add to the red total move.w d3,d5 ;restore original d5 here move.l a5,a0 ;restore original a0 here sub.w d6,d7 ;adjust X for remainder bne.w @ScaleColEnd ;if we don't need next pixel, skip swap d6 ;get dstWidth in d6 move.w d6,d7 ;reset X counter for new pixel swap d6 ;restore X counter addq.l #4,a0 ;point to it in memory bra.w @ScaleColEnd ;loop for the next pixel ;------------------------- ScaleXY ---------------------------- @ScaleXY: move.l a0,-(sp) ;save a0 on the stack swap d7 ;swap d7 move.w d5,d7 ;save d5.l there swap d7 ;safely in the high word move.w d7,d2 ;save d7 in d2 swap d2 ;(high word) move.w d6,d2 ;and save d6 in the low @ScaleXYLoopY: move.l a0,a5 ;copy a0 to a5 for now @ScaleXYLoopX: move.w d7,d3 ;get X multiplier in d3 mulu.w d5,d3 ;times Y multiplier ; moveq.l #10,d0 ;get divisor in d0 lsr.l #4,d3 ;shift off extra bits move.l (a0)+,d1 ;get the next pixel clr.w d0 move.b d1,d0 ;get the blue into d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d3,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a2 ;add to the red total sub.w d7,d6 ;adjust X for remainder swap d6 ;get dest width in d6 move.w d6,d7 ;reset X count for the new pixel swap d6 ;restore X count cmp.w d6,d7 ;still another whole pixel to go? blt.s @ScaleXYLoopX ;if so, loop again move.w d6,d3 ;get X multiplier in d3 mulu.w d5,d3 ;times Y multiplier ; moveq.l #10,d0 ;get divisor in d0 lsr.l #4,d3 ;shift off 8 bits move.l (a0),d1 ;get the next pixel clr.w d0 move.b d1,d0 ;get the blue into d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d3,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a2 ;add to the red total move.w d2,d6 ;restore source counter in d6 swap d2 ;swap to get the low word move.w d2,d7 ;restore source remainder in d7 swap d2 ;swap things back for the future movea.l a5,a0 ;restore a0 add.l srcRow(a6),a0 ;point to the next row sub.w d5,d4 ;adjust Y for remainder swap d4 ;get destination height in d4 move.w d4,d5 ;reset Y count for the new pixel swap d4 ;restore Y count cmp.w d4,d5 ;still another whole pixel to go? blt.s @ScaleXYLoopY ;if so, loop again move.l a0,d0 ;copy current a0 into d0 sub.l d0,(sp) ;subtract it from old a0 @ScaleXYLoopX2: move.w d7,d3 ;get X multiplier in d3 mulu.w d4,d3 ;times Y multiplier ; moveq.l #10,d0 ;get divisor in d0 lsr.l #4,d3 ;shift off extra bits move.l (a0)+,d1 ;get the next pixel clr.w d0 move.b d1,d0 ;get the blue into d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d3,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a2 ;add to the red total sub.w d7,d6 ;adjust X for remainder swap d6 ;get dest width in d6 move.w d6,d7 ;reset X count for the new pixel swap d6 ;restore X count cmp.w d6,d7 ;still another whole pixel to go? blt.s @ScaleXYLoopX2 ;if so, loop again move.w d6,d3 ;get X multiplier in d3 mulu.w d4,d3 ;times Y multiplier ; moveq.l #10,d0 ;get divisor in d0 lsr.l #4,d3 ;shift off extra bits move.l (a0),d1 ;get the next pixel clr.w d0 move.b d1,d0 ;get the blue into d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a4 ;add to the blue total move.w d1,d0 ;get pixel again lsr.w #8,d0 ;shift to get the green mulu.w d3,d0 ;times remainder of the source add.l d0,a3 ;add to the green total swap d1 ;swap the red into the low byte clr.l d0 ;clear out d0 move.b d1,d0 ;get the red in d0 mulu.w d3,d0 ;times remainder of the source add.l d0,a2 ;add to the red total sub.w d6,d7 ;adjust X for remainder bne.s @SXYSave ;if we don't need next pixel, skip swap d6 ;get dest. width in d6 move.w d6,d7 ;reset X counter for new pixel swap d6 ;restore X counter addq.l #4,a0 ;point to it in memory @SXYSave: swap d7 ;swap d7's words move.w d7,d5 ;restore d5.l swap d7 ;put things back adda.l (sp)+,a0 ;point back to original row move.l a2,d1 ;get red in d1 move.l a3,d0 ;get green in d0 lsr.l #8,d0 ;shift it down 8 bits move.w d0,d1 ;copy the resulting word in move.l a4,d0 ;get blue in d0 swap d0 ;swap it low move.b d0,d1 ;copy the last byte in move.l d1,(a1)+ ;store that to the output bra.w @ScaleColSkip ;continue the loop @ScaleExit: add.l #4,sp ;pop off region position move.l (sp)+,d0 ;get length of buffer add.l d0,sp ;get it off the stack movem.l (sp)+,d3-d7/a2-a6 ;get registers from the stack \ No newline at end of file diff --git a/Source/68020/CopyTo32.a b/Source/68020/CopyTo32.a new file mode 100644 index 0000000..9db7fa8 --- /dev/null +++ b/Source/68020/CopyTo32.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; a0 = pointer to the 24-bit source pixmap row ; a1 = pointer to the 8-bit destination pixmap row ; d2 = pointer to the region buffer ; d7 = (low word) column count ; ; The following registers will be modified: ; ; d0,d1,d2,d3,d4,d5,d6,d7 ; a0,a1,a3 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = accumulator ; d6 = (low word) region column counter ; d7 = (low word) column counter ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = pointer to region buffer ; move.l d2,a2 ;and the real a2 from d2 subq.w #1,d7 ;subtract 1 from the width for dbra ; ; Set up the region column counter in d6 ; move.w (a2)+,d6 ;get region start in d6 bne.s @CopyLoop ;if not zero, skip over this business sub.w (a2)+,d6 ;otherwise, subtract the next word ; ; Determine whether or not to draw this pixel, and handle switches ; @CopyLoop: tst.w d6 ;is d6 negative? bmi.s @CopyStore ;if so, store this value addq.w #4,a0 ;skip past the current source pixel addq.w #4,a1 ;skip past the current dest. pixel subq.w #1,d6 ;decrement this counter bne.s @CopyCont ;if non-zero continue sub.w (a2)+,d6 ;get the negative of the next value add.w -4(a2),d6 ;and add the previous one bra.s @CopyCont ;continue @CopyStore: move.l (a0)+,(a1)+ ;store the value to the output addq.w #1,d6 ;increment the counter bne.s @CopyCont ;if non-zero, continue move.w (a2)+,d6 ;get the next value sub.w -4(a2),d6 ;minus the previous ; ; End of loop: go until done ; @CopyCont: dbra.w d7,@CopyLoop ;loop until done \ No newline at end of file diff --git a/Source/68020/CopyUnscaledFrom32.a b/Source/68020/CopyUnscaledFrom32.a new file mode 100644 index 0000000..8f9f083 --- /dev/null +++ b/Source/68020/CopyUnscaledFrom32.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; srcBase = (long) pointer to the first source pixel ; srcRow = (long) rowBytes for the source pixmap ; dstBase = (long) pointer to the first destination pixel ; dstRow = (long) rowBytes for the destination pixmap ; itAddr = (long) pointer to the inverse color table ; ctAddr = (long) pointer to the color table ; theRgn = (long) handle to the destination region ; boxRect = (Rect) the bounding rectangle of this region ; height = (word) height of the region bounding box ; width = (word) width of the region bounding box ; even = (long) pointer to the even row dithering routine ; odd = (long) pointer to the odd row dithering routine ; evodd = (short) word holding even/odd row information ; ; The following registers will be modified: ; ; d0,d1,d2 ; a0,a1 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = accumulator ; d6 = row counter ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = pointer to inverse color table ; a3 = pointer to color table ; movem.l d3-d7/a2-a6,-(sp) ;save the registers move.l 48(sp),a6 ;get the address of the CopyData structure in a6 ;(based off stack: 10 registers + 1 a6 link + 1 return addr. ; = 12 * 4 bytes = 48 bytes) ; ; Allocate space on the stack for our buffers ; clr.l d0 ;zero out d0 move.w width(a6),d0 ;get row width in d0 addq.l #2,d0 ;plus two for overflow lsl.l #2,d0 ;width * 4 move.l d0,d1 ;copy to d1 lsl.l #1,d0 ;width * 8 add.l d1,d0 ;width * 12 sub.l d0,sp ;make that much room on the stack move.l d0,-(sp) ;push the length move.l d0,d1 ;copy to d1 moveq.l #10,d0 ;offset by 10 bytes = 6 bytes + 4 for length add.l sp,d0 ;add in current stack pointer move.l d0,evenAddr(a6) ;save as evenAddr lsr.l #1,d1 ;divide length by two add.l d1,d0 ;add to this pointer move.l d0,oddAddr(a6) ;save as oddAddr ; ; Clear out the dithering buffers ; subq.l #4,d1 ;decrement d1 for the dbra, plus the extras move.l evenAddr(a6),a0 ;point a0 to the even address @ClearLoop: clr.w (a0)+ ;clear the word at a0 dbra.w d1,@ClearLoop ;loop until done ; ; Initialize the region data ; move.l theRgn(a6),a0 ;get theRgn in a0 lea.l rgnBuffer(a6),a1 ;point a1 to the region buffer move.w boxRect+0(a6),d2 ;get box top in d2 move.w boxRect+2(a6),d3 ;box left in d3 move.w height(a6),d4 ;height in d4 move.w width(a6),d5 ;width in d5 jsr InitRegion ;initialize the region move.l a0,-(sp) ;store our pointer to the rgn on the stack ; ; Set up our pointers and the row counter ; move.l srcBase(a6),a0 ;get the base for the source move.l dstBase(a6),a1 ;get the base for the destination move.l itAddr(a6),a2 ;point a2 to the inverse color table move.l ctAddr(a6),a3 ;point a3 to the color table move.w height(a6),d6 ;get the height of the destination in d6 subq.w #1,d6 ;minus one = row counter ; ; Beginning of outer (row) loop: determine even/odd and dither ; @RowLoop: move.l a0,-(sp) ;save source row pointer move.l a1,-(sp) ;save dest row pointer move.w width(a6),d7 ;get the width in d7 lea.l rgnBuffer+4(a6),a4 ;get rgnBuffer address in a4 move.l a4,d2 ;point d2 (a6) to the region buffer move.l evenAddr(a6),d0 ;point d0 (a4) to the even buffer move.l oddAddr(a6),d1 ;point d1 (a5) to the odd buffer move.l d6,-(sp) ;save d6 on the stack move.l errTable(a6),d6 ;point d6 to the error table bchg.b #0,evodd+1(a6) ;check the even/odd flag beq.s @RLEven ;if zero, dither evenly move.l odd(a6),a4 ;get jump address jsr (a4) ;otherwise, dither oddly bra.s @RLEnd ;skip ahead @RLEven: move.l even(a6),a4 ;get subroutine address here jsr (a4) ;dither the even row ; ; Restore our state and increment by one row ; @RLEnd: move.l (sp)+,d6 ;get d6 from the stack tst.w d6 ;are we done? beq.s @DitherDone1 ;if we are, don't crash :-) ; ; Decrement the region Y counter and merge in the next scan line ; subq.w #1,rgnBuffer(a6) ;decrement the Y count bne.s @RgnOk ;skip if we're not done move.l 8(sp),a0 ;get region pointer lea.l rgnBuffer+4(a6),a1 ;point a1 into the region buffer move.w boxRect+2(a6),d0 ;get left end of the box in d0 jsr UpdateRegion ;update our region move.l a0,8(sp) ;save new position again ; ; End of row loop: adjust pointers and loop until done ; @RgnOk: move.l (sp)+,a1 ;restore the destination ptr add.l dstRow(a6),a1 ;increment by one row move.l (sp)+,a0 ;restore the source ptr add.l srcRow(a6),a0 ;increment by one row dbra.w d6,@RowLoop ;loop for more rows addq.l #4,sp ;pop off region position bra.s @DitherDone ;skip ahead @DitherDone1: add.l #12,sp ;pop off region, a0, a1 positions @DitherDone: move.l (sp)+,d0 ;get the amount of extra space add.l d0,sp ;remove it from the stack movem.l (sp)+,d3-d7/a2-a6 ;restore the registers \ No newline at end of file diff --git a/Source/68020/CustomCopyBits.a b/Source/68020/CustomCopyBits.a new file mode 100644 index 0000000..b2db125 --- /dev/null +++ b/Source/68020/CustomCopyBits.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ machine mc68020 ; ; Offsets of the various parameters in CopyData ; ctAddr equ 0 itAddr equ 4 evenAddr equ 8 oddAddr equ 12 even equ 16 odd equ 20 errTable equ 24 srcRow equ 28 dstRow equ 32 srcBase equ 36 dstBase equ 40 rgnBuffer equ 44 width equ 1068 height equ 1070 evodd equ 1072 theRgn equ 1074 boxRect equ 1078 srcHeight equ 1086 srcWidth equ 1088 dstHeight equ 1090 dstWidth equ 1092 xRemainder equ 1094 yRemainder equ 1096 columns equ 1098 rows equ 1100 outputAddr equ 1102 sTable equ 1106 ; ; void CopyUnscaledFrom32(CopyDataPtr theData) ; CopyUnscaledFrom32 proc export import InitRegion,UpdateRegion link a6,#0 include 'CopyUnscaledFrom32.a' unlk a6 rts endp ; ; void CopyScaledFrom32(CopyDataPtr theData) ; CopyScaledFrom32 proc export import InitRegion,UpdateRegion link a6,#0 include 'CopyScaledFrom32.a' unlk a6 rts endp ; ; void CopyFastScaledFrom32(CopyDataPtr theData) ; CopyFastScaledFrom32 proc export import InitRegion,UpdateRegion link a6,#0 include 'CopyFastScaledFrom32.a' unlk a6 rts endp ; ; void CopyReallyFastScaledFrom32(CopyDataPtr theData) ; CopyReallyFastScaledFrom32 proc export import InitRegion,UpdateRegion link a6,#0 include 'CopyReallyFastScaledFrom32.a' unlk a6 rts endp CopyTo32 proc export include 'CopyTo32.a' rts endp DitherCopyTo16Even proc export include 'DitherCopyTo16Even.a' rts endp DitherCopyTo16Odd proc export include 'DitherCopyTo16Odd.a' rts endp DitherCopyTo8Even proc export include 'DitherCopyTo8Even.a' rts endp DitherCopyTo8Odd proc export include 'DitherCopyTo8Odd.a' rts endp InitRegion proc export include 'InitRegion.a' rts endp UpdateRegion proc export include 'UpdateRegion.a' rts endp end \ No newline at end of file diff --git a/Source/68020/DecodeDummyRow.a b/Source/68020/DecodeDummyRow.a new file mode 100644 index 0000000..7fbb1a3 --- /dev/null +++ b/Source/68020/DecodeDummyRow.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ movem.l d3-d7/a2-a4/a6,-(sp) ;Save all registers move.l 44(sp),a6 ;get the address of the CopyData structure in a6 ;(based off stack: 9 registers + 1 a6 link + 1 return addr. ; = 12 * 4 bytes = 48 bytes) movem.l store(a6),d1-d7/a0/a2-a4;Restore some important variables movea.l dest(a6),a1 ;Point a1 to the destination tst.l a1 ;Are we just initializing? beq.w @InitTree ;If so, do it and get outta here move.w width(a6),d1 ;Get the width in d1 subq.w #1,d1 ;Decrement for dbra instruction @ILoop: cmpa.l a4,a2 ;Is the stack empty? beq.s @NewCode ;If so, get a new code ;***** move.b -(a2),(a1)+ ;Otherwise, copy to destination subq.w #1,a2 ;Otherwise, pull a byte off the stack @EndI: dbra.w d1,@ILoop ;Decrement and loop until done clr.b theReturn(a6) ;Store false bra.w @Return ;Return and exit ; ; Get a new code of the appropriate length = (lo)d2 ; @NewCode: swap d1 ;Low word of d1 = byte count swap d4 ;Low word of d4 = bits in buffer @NCLoop: cmp.w d4,d2 ;Compare the code size to the buffer size ble.s @GotCode ;If there's enough we're done tst.w d1 ;Any more bytes available? bne.s @NCAddByte ;If so, skip ahead move.b (a0)+,d1 ;Get a new byte count beq.w @ReturnT ;Return true if zero @NCAddByte: subq.w #1,d1 ;Decrement the byte count clr.l d0 ;Clear the accumulator move.b (a0)+,d0 ;Get the next byte lsl.l d4,d0 ;Shift these new bits over or.l d0,d3 ;Or them into the buffer addq.w #8,d4 ;Adjust the buffer size bra.s @NCLoop ;Loop until we have enough bits @GotCode: move.l d3,d0 ;Copy buffer into accumulator swap d7 ;Low word of d7 = (1 << codeSize) - 1 and.w d7,d0 ;Keep only as many bits as we need swap d7 ;Put it back in the high word lsr.l d2,d3 ;Shift these bits out of the buffer sub.w d2,d4 ;Adjust the bitcount of the buffer swap d4 ;Low word of d4 = tree size swap d1 ;Low word of d1 = column counter ; ; Process the code ; cmp.w d5,d0 ;Clear code? beq.w @ClrTree ;If so, reset the LZW tree swap d5 ;Low word of d5 = endCode cmp.w d5,d0 ;End code? beq.w @ReturnT ;If so, return with a true swap d5 ;Otherwise put d5 back ; ; Handle a normal code ; swap d6 ;Low word of d6 = old move.w d0,d6 ;Save a copy of the current code in d6 swap d6 ;In the high word cmp.w d4,d0 ;Is it a valid code? blt.s @DecLoop ;If so, continue bne.w @SignalError ;//If not equal to tree size, then invalid swap d2 ;Otherwise, low word of d2 = first move.b d2,(a2)+ ;Push that on the stack swap d2 ;Restore d2 move.w d6,d0 ;Current code = last code @DecLoop: cmp.w d5,d0 ;Is the code greater than clear code? blt.s @DecDone ;Skip out if so move.l (0,a3,d0.w*4),d0 ;Get the parent and code for this node move.b d0,(a2)+ ;Push code on the stack swap d0 ;Get the parent in the low word bra.s @DecLoop ;Loop until we're done @DecDone: ;***** move.b d0,(a1)+ ;Send this last guy to the output swap d2 ;Low word of d2 = first move.w d0,d2 ;Store this for later swap d2 ;In the high word ; ; Add a new node, if there's room ; cmpi.w #4096,d4 ;Is the tree max'ed out? bge.s @EndI ;If so, just loop swap d0 ;Swap the current node high move.w d6,d0 ;Put last into d0 swap d0 ;Back to the correct order swap d6 ;Set last = old move.l d0,(0,a3,d4.w*4) ;Add this to the tree addq.w #1,d4 ;Increment the tree size cmp.w d7,d4 ;Should we increase the code size? blt.w @EndI ;If not, just loop cmpi.w #12,d2 ;*Can* we increase the code size? beq.w @EndI ;If not, just loop lsl.l #1,d7 ;Shift both words of d7 up one bit ori.l #65536,d7 ;OR in a new mask bit (65536 == $00010000) addq.w #1,d2 ;Increment the code size bra.w @EndI ;Loop for some more ; ; Initialize the LZW tree ; @InitTree: movea.l src(a6),a0 ;Get the input address movea.l tree(a6),a3 ;Get the tree address clr.w d0 ;Clear d0 move.b (a0)+,d0 ;Get the char size in d0 move.w d0,charSize(a6) ;Store this elsewhere movea.l stack(a6),a2 ;Point a2 to the stack move.l a2,a4 ;Copy this into a4 clr.l d1 ;Erase d1 clr.l d3 ;Erase d3 moveq.l #1,d4 ;Set the tree size to 1 lsl.l d0,d4 ;Shift it left by char size move.w d4,d5 ;Copy it to d5 for the end code addq.w #1,d5 ;Increment by 1 = end code swap d5 ;Put that into the high word move.w d4,d5 ;Copy tree size into low word = clear addq.w #2,d4 ;tree size += 2 addq.w #1,d0 ;Increment the char size = code size move.w d0,d2 ;Store as the code size move.l #65537,d7 ;Put 1's in high & low of d7 (65537 == $00010001) lsl.l d0,d7 ;Shift left by code size subi.l #65536,d7 ;Decrement the high word by 1 (65536 == $00010000) bra.s @ReturnT ;Return a true ; ; Reset the LZW tree ; @ClrTree: move.w charSize(a6),d0 ;Get charSize move.w #1,d4 ;Set the tree size to 1 lsl.w d0,d4 ;Shift it left by charSize addq.w #2,d4 ;Tree size += 2 addq.w #1,d0 ;Increment the char size = code size move.w d0,d2 ;Store as the code size move.l #65537,d7 ;Put 1's in high & low of d7 (65537 == $00010001) lsl.l d0,d7 ;Shift left by code size subi.l #65536,d7 ;Decrement the high word by 1 (65536 == $00010000) ; ; Get a new code of the appropriate length = (lo)d2 ; swap d1 ;Low word of d1 = byte count swap d4 ;Low word of d4 = bits in buffer @CCLoop: cmp.w d4,d2 ;Compare the code size to the buffer size ble.s @CGtCode ;If there's enough we're done tst.w d1 ;Any more bytes available? bne.s @CCAddByte ;If so, skip ahead move.b (a0)+,d1 ;Get a new byte count beq.s @ReturnT ;Return true if zero @CCAddByte: subq.w #1,d1 ;Decrement the byte count clr.l d0 ;Clear the accumulator move.b (a0)+,d0 ;Get the next byte lsl.l d4,d0 ;Shift these new bits over or.l d0,d3 ;Or them into the buffer addq.w #8,d4 ;Adjust the buffer size bra.s @CCLoop ;Loop until we have enough bits @CGtCode: move.l d3,d0 ;Copy buffer into accumulator swap d7 ;Low word of d7 = (1 << codeSize) - 1 and.w d7,d0 ;Keep only as many bits as we need swap d7 ;Put it back in the high word lsr.l d2,d3 ;Shift these bits out of the buffer sub.w d2,d4 ;Adjust the bitcount of the buffer cmp.w d5,d0 ;Is it another clear code? beq.s @CCLoop ;If so, get another code swap d4 ;Low word of d4 = tree size swap d1 ;Low word of d1 = column counter ;***** move.b d0,(a1)+ ;Store this as the output swap d2 ;Low word of d2 = first move.w d0,d2 ;This code is also first swap d2 ;But in the high word move.w d0,d6 ;It's also the last bra.w @EndI ;Continue on ; ; Return to the program ; @ReturnT: move.b #1,theReturn(a6) ;Store a one @Return: move.l theEnd(a6),a1 ;Get the end of data pointer cmp.l a0,a1 ;Did we pass the end of data? bgt.s @NoError ;If not, no error @SignalError: clr.l theEnd(a6) @NoError: movem.l d1-d7/a0/a2-a4,store(a6);Save some important variables movem.l (sp)+,d3-d7/a2-a4/a6 ;Restore all registers \ No newline at end of file diff --git a/Source/68020/DecodeRow.a b/Source/68020/DecodeRow.a new file mode 100644 index 0000000..507a43e --- /dev/null +++ b/Source/68020/DecodeRow.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ movem.l d3-d7/a2-a4/a6,-(sp) ;//Save all registers move.l 44(sp),a6 ;//get the address of the CopyData structure in a6 ;//(based off stack: 9 registers + 1 a6 link + 1 return addr. ;// = 12 * 4 bytes = 48 bytes) movem.l store(a6),d1-d7/a0/a2-a4;//Restore some important variables movea.l dest(a6),a1 ;//Point a1 to the destination tst.l a1 ;//Are we just initializing? beq.w @InitTree ;//If so, do it and get outta here move.w width(a6),d1 ;//Get the width in d1 subq.w #1,d1 ;//Decrement for dbra instruction @ILoop: cmpa.l a4,a2 ;//Is the stack empty? beq.s @NewCode ;//If so, get a new code move.b -(a2),(a1)+ ;//Otherwise, copy to destination @EndI: dbra.w d1,@ILoop ;//Decrement and loop until done clr.b theReturn(a6) ;//Store false bra.w @Return ;//Return and exit ;// ;// Get a new code of the appropriate length = (lo)d2 ;// @NewCode: swap d1 ;//Low word of d1 = byte count swap d4 ;//Low word of d4 = bits in buffer @NCLoop: cmp.w d4,d2 ;//Compare the code size to the buffer size ble.s @GotCode ;//If there's enough we're done tst.w d1 ;//Any more bytes available? bne.s @NCAddByte ;//If so, skip ahead move.b (a0)+,d1 ;//Get a new byte count beq.w @ReturnT ;//Return true if zero @NCAddByte: subq.w #1,d1 ;//Decrement the byte count clr.l d0 ;//Clear the accumulator move.b (a0)+,d0 ;//Get the next byte lsl.l d4,d0 ;//Shift these new bits over or.l d0,d3 ;//Or them into the buffer addq.w #8,d4 ;//Adjust the buffer size bra.s @NCLoop ;//Loop until we have enough bits @GotCode: move.l d3,d0 ;//Copy buffer into accumulator swap d7 ;//Low word of d7 = (1 << codeSize) - 1 and.w d7,d0 ;//Keep only as many bits as we need swap d7 ;//Put it back in the high word lsr.l d2,d3 ;//Shift these bits out of the buffer sub.w d2,d4 ;//Adjust the bitcount of the buffer swap d4 ;//Low word of d4 = tree size swap d1 ;//Low word of d1 = column counter ;// ;// Process the code ;// cmp.w d5,d0 ;//Clear code? beq.w @ClrTree ;//If so, reset the LZW tree swap d5 ;//Low word of d5 = endCode cmp.w d5,d0 ;//End code? beq.w @ReturnT ;//If so, return with a true swap d5 ;//Otherwise put d5 back ;// ;// Handle a normal code ;// swap d6 ;//Low word of d6 = old move.w d0,d6 ;//Save a copy of the current code in d6 swap d6 ;//In the high word cmp.w d4,d0 ;//Is it a valid code? blt.s @DecLoop ;//If so, continue bne.w @SignalError ;//If not equal to tree size, then invalid swap d2 ;//Otherwise, low word of d2 = first move.b d2,(a2)+ ;//Push that on the stack swap d2 ;//Restore d2 move.w d6,d0 ;//Current code = last code @DecLoop: cmp.w d5,d0 ;//Is the code greater than clear code? blt.s @DecDone ;//Skip out if so move.l (0,a3,d0.w*4),d0 ;//Get the parent and code for this node move.b d0,(a2)+ ;//Push code on the stack swap d0 ;//Get the parent in the low word bra.s @DecLoop ;//Loop until we're done @DecDone: move.b d0,(a1)+ ;//Send this last guy to the output swap d2 ;//Low word of d2 = first move.w d0,d2 ;//Store this for later swap d2 ;//In the high word ;// ;// Add a new node, if there's room ;// cmpi.w #4096,d4 ;//Is the tree max'ed out? bge.w @EndI ;//If so, just loop swap d0 ;//Swap the current node high move.w d6,d0 ;//Put last into d0 swap d0 ;//Back to the correct order swap d6 ;//Set last = old move.l d0,(0,a3,d4.w*4) ;//Add this to the tree addq.w #1,d4 ;//Increment the tree size cmp.w d7,d4 ;//Should we increase the code size? blt.w @EndI ;//If not, just loop cmpi.w #12,d2 ;//*Can* we increase the code size? beq.w @EndI ;//If not, just loop lsl.l #1,d7 ;//Shift both words of d7 up one bit ori.l #65536,d7 ;//OR in a new mask bit (65536 == $00010000) addq.w #1,d2 ;//Increment the code size bra.w @EndI ;//Loop for some more ;// ;// Initialize the LZW tree ;// @InitTree: movea.l src(a6),a0 ;//Get the input address movea.l tree(a6),a3 ;//Get the tree address clr.w d0 ;//Clear d0 move.b (a0)+,d0 ;//Get the char size in d0 move.w d0,charSize(a6) ;//Store this elsewhere movea.l stack(a6),a2 ;//Point a2 to the stack move.l a2,a4 ;//Copy this into a4 clr.l d1 ;//Erase d1 clr.l d3 ;//Erase d3 moveq.l #1,d4 ;//Set the tree size to 1 lsl.l d0,d4 ;//Shift it left by char size move.w d4,d5 ;//Copy it to d5 for the end code addq.w #1,d5 ;//Increment by 1 = end code swap d5 ;//Put that into the high word move.w d4,d5 ;//Copy tree size into low word = clear addq.w #2,d4 ;//tree size += 2 addq.w #1,d0 ;//Increment the char size = code size move.w d0,d2 ;//Store as the code size move.l #65537,d7 ;//Put 1's in high & low of d7 (65537 == $00010001) lsl.l d0,d7 ;//Shift left by code size subi.l #65536,d7 ;//Decrement the high word by 1 (65536 == $00010000) bra.s @ReturnT ;//Return a true ;// ;// Reset the LZW tree ;// @ClrTree: move.w charSize(a6),d0 ;//Get charSize move.w #1,d4 ;//Set the tree size to 1 lsl.w d0,d4 ;//Shift it left by charSize addq.w #2,d4 ;//Tree size += 2 addq.w #1,d0 ;//Increment the char size = code size move.w d0,d2 ;//Store as the code size move.l #65537,d7 ;//Put 1's in high & low of d7 (65537 == $00010001) lsl.l d0,d7 ;//Shift left by code size subi.l #65536,d7 ;//Decrement the high word by 1 (65536 == $00010000) ;// ;// Get a new code of the appropriate length = (lo)d2 ;// swap d1 ;//Low word of d1 = byte count swap d4 ;//Low word of d4 = bits in buffer @CCLoop: cmp.w d4,d2 ;//Compare the code size to the buffer size ble.s @CGtCode ;//If there's enough we're done tst.w d1 ;//Any more bytes available? bne.s @CCAddByte ;//If so, skip ahead move.b (a0)+,d1 ;//Get a new byte count beq.s @ReturnT ;//Return true if zero @CCAddByte: subq.w #1,d1 ;//Decrement the byte count clr.l d0 ;//Clear the accumulator move.b (a0)+,d0 ;//Get the next byte lsl.l d4,d0 ;//Shift these new bits over or.l d0,d3 ;//Or them into the buffer addq.w #8,d4 ;//Adjust the buffer size bra.s @CCLoop ;//Loop until we have enough bits @CGtCode: move.l d3,d0 ;//Copy buffer into accumulator swap d7 ;//Low word of d7 = (1 << codeSize) - 1 and.w d7,d0 ;//Keep only as many bits as we need swap d7 ;//Put it back in the high word lsr.l d2,d3 ;//Shift these bits out of the buffer sub.w d2,d4 ;//Adjust the bitcount of the buffer cmp.w d5,d0 ;//Is it another clear code? beq.s @CCLoop ;//If so, get another code swap d4 ;//Low word of d4 = tree size swap d1 ;//Low word of d1 = column counter move.b d0,(a1)+ ;//Store this as the output swap d2 ;//Low word of d2 = first move.w d0,d2 ;//This code is also first swap d2 ;//But in the high word move.w d0,d6 ;//It's also the last bra.w @EndI ;//Continue on ;// ;// Return to the program ;// @ReturnT: move.b #1,theReturn(a6) ;//Store a one @Return: move.l theEnd(a6),a1 ;//Get the end of data pointer cmp.l a0,a1 ;//Did we pass the end of data? bgt.s @NoError ;//If not, no error @SignalError: clr.l theEnd(a6) @NoError: movem.l d1-d7/a0/a2-a4,store(a6);//Save some important variables movem.l (sp)+,d3-d7/a2-a4/a6 ;//Restore all registers \ No newline at end of file diff --git a/Source/68020/DitherCopyTo16Even.a b/Source/68020/DitherCopyTo16Even.a new file mode 100644 index 0000000..7b960d8 --- /dev/null +++ b/Source/68020/DitherCopyTo16Even.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; a0 = pointer to the 24-bit source pixmap row ; a1 = pointer to the 8-bit destination pixmap row ; a2 = pointer to the inverse color table ; a3 = pointer to the color table ; d0 = pointer to the even row dithering buffer ; d1 = pointer to the odd row dithering buffer ; d2 = pointer to the region buffer ; d7 = (low word) column count ; ; The following registers will be modified: ; ; d0,d1,d2,d3,d4,d5,d6,d7 ; a0,a1,a3 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = accumulator ; d2 = current sum of red components (<< 4) ; d3 = current sum of green components (<< 4) ; d4 = current sum of blue components (<< 4) ; d5 = (low word) ANDing mask = 0x0ff0 ; d5 = (high word) temporary storage for red error ; d6 = (low word) region column counter ; d6 = (high word) temporary storage for green error ; d7 = (low word) column counter ; d7 = (high word) temporary storage for blue error ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = pointer to inverse color table ; a3 = pointer to color table ; a4 = pointer to even dithering buffer ; a5 = pointer to odd dithering buffer ; a6 = pointer to region buffer ; movem.l a5/a6,-(a7) ;save a5/a6 on the stack move.l d0,a4 ;get the real a4 from d0 move.l d1,a5 ;and the real a5 from d1 move.l d2,a6 ;and the real a6 from d2 ; ; Initialize our counters and clear out next row ; subq.w #1,d7 ;subtract 1 from the width for dbra move.w #4080,d5 ;use d5 as a useful anding mask clr.w d2 ;clear the leftover dithering: red clr.w 0(a5) ;clear the odd row dithering: red clr.w d3 ;green clr.w 2(a5) ;green clr.w d4 ;blue clr.w 4(a5) ;blue ; ; Set up the region column counter in d6 ; move.w (a6)+,d6 ;get region start in d6 bne.s @EvenLoop ;if not zero, skip over this business sub.w (a6)+,d6 ;otherwise, subtract the next word bra.s @EvenLoop ;start by updating the region ; ; Clamp over/underflows to 255/0 ; @FixRed: spl.b d2 ;if negative, set to 0, else set to ff lsl.w #4,d2 ;shift up 4 bits and.w d5,d2 ;and with d5 bra.s @RedRet ;return @FixGreen: spl.b d3 ;if negative, set to 0, else set to ff lsl.w #4,d3 ;shift up 4 bits and.w d5,d3 ;and with d5 bra.s @GreenRet ;return @FixBlue: spl.b d4 ;if negative, set to 0, else set to ff lsl.w #4,d4 ;shift up 4 bits and.w d5,d4 ;and with d5 bra.s @BlueRet ;return @EvenLoop: swap d7 ;save the column counter ; ; Combine the various parts of the dithered pixel ; move.l (a0)+,d1 ;get source pixel move.l d1,d0 ;copy to d0 add.w (a4)+,d2 ;get dithering from previous row: red lsl.l #4,d0 ;shift pixel value up by 4 and.w d5,d0 ;isolate the blue add.w d0,d4 ;add to the blue total add.w (a4)+,d3 ;get dithering from previous row: green swap d0 ;get red part in lower 8 bits and.w d5,d0 ;keep only the good bits add.w d0,d2 ;add it to the leftover red add.w (a4)+,d4 ;get dithering from previous row: blue lsr.w #4,d1 ;shift pixel down by 4 (upper 8 bits << 4) and.w d5,d1 ;keep only the good bits add.w d1,d3 ;add it to the leftover green ; ; Round, check for overflows, and handle them ; addq.w #8,d2 ;add 1/2 a pixel to the total bftst d2{16:4} ;check bits 12-15 for red overflow bne.s @FixRed ;if it's set, fix up the red @RedRet: addq.w #8,d3 ;add 1/2 a pixel to the total bftst d3{16:4} ;check bits 12-15 for green overflow bne.s @FixGreen ;if it's set, fix up the green @GreenRet: addq.w #8,d4 ;add 1/2 a pixel to the total bftst d4{16:4} ;check bits 12-15 for blue overflow bne.s @FixBlue ;if it's set, fix up the blue @BlueRet: ; ; Calculate the 16-bit pixel value ; move.w d4,d0 ;get the blue bits in d0 ror.l #8,d0 ;rotate them off the right side ror.l #4,d0 ;(12 bits -- we do it in two steps) move.w d3,d0 ;get the green bits in d0 lsr.w #7,d0 ;shift off the low three bits ror.l #5,d0 ;rotate them off the right side move.w d2,d0 ;get the red bits in d0 lsr.w #7,d0 ;shift off the low three bits ror.l #6,d0 ;rotate off the right side swap d0 ;swap the result into the low word ; ; Determine whether or not to draw this pixel, and handle switches ; tst.w d6 ;is d6 negative? bmi.s @EvenStore ;if so, store this value addq.w #2,a1 ;skip past the current pixel subq.w #1,d6 ;decrement this counter bne.s @EvenCont ;if non-zero continue sub.w (a6)+,d6 ;get the negative of the next value add.w -4(a6),d6 ;and add the previous one bra.s @EvenCont ;continue @EvenStore: move.w d0,(a1)+ ;store the value to the output addq.w #1,d6 ;increment the counter bne.s @EvenCont ;if non-zero, continue move.w (a6)+,d6 ;get the next value sub.w -4(a6),d6 ;minus the previous ; ; Get the real color for this entry ; @EvenCont: move.w d2,d0 ;get red value in d0 lsr.w #7,d0 ;shift down 7 bits move.w d0,d1 ;copy to d1 lsl.w #5,d0 ;shift back 5 bits add.w d0,d1 ;add together lsl.w #2,d1 ;shift up two more sub.w d1,d2 ;subtract from desired red move.w d3,d0 ;get green value in d0 lsr.w #7,d0 ;shift down 7 bits move.w d0,d1 ;copy to d1 lsl.w #5,d0 ;shift back 5 bits add.w d0,d1 ;add together lsl.w #2,d1 ;shift up two more sub.w d1,d3 ;subtract from desired green move.w d4,d0 ;get blue value in d0 lsr.w #7,d0 ;shift down 7 bits move.w d0,d1 ;copy to d1 lsl.w #5,d0 ;shift back 5 bits add.w d0,d1 ;add together lsl.w #2,d1 ;shift up two more sub.w d1,d4 ;subtract from desired blue ; ; Divide the real color by 16 and set up to calculate odd multiples ; swap d5 ;save the 0x0ff0 mask swap d6 ;save our region info asr.w #4,d2 ;divide the error by 16: red asr.w #4,d3 ;green asr.w #4,d4 ;blue move.w d2,d5 ;copy this value to d5-d7: red move.w d3,d6 ;green move.w d4,d7 ;blue add.w d5,d5 ;double it in d5-d7: red add.w d6,d6 ;green add.w d7,d7 ;blue ; ; Store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor ; movem.w d2-d4,6(a5) ;store 1/16 at (+1,+1): red/green/blue add.w d5,d2 ;add 2 * error = 3/16: red add.w d6,d3 ;green add.w d7,d4 ;blue add.w d2,-6(a5) ;add 3/16 to (-1,+1): red add.w d5,d2 ;add 2 * error = 5/16: red add.w d3,-4(a5) ;green add.w d6,d3 ;green add.w d4,-2(a5) ;blue add.w d7,d4 ;blue add.w d2,(a5)+ ;add 5/16 to (0,+1): red add.w d5,d2 ;add 2 * error = 7/16: red add.w d3,(a5)+ ;green add.w d6,d3 ;green add.w d4,(a5)+ ;blue add.w d7,d4 ;blue swap d6 ;restore our region info swap d5 ;restore 0x0ff0 mask ; ; End of loop: go until done ; swap d7 ;restore column counter dbra.w d7,@EvenLoop ;loop until done movem.l (sp)+,a5/a6 ;restore a5/a6 from the stack \ No newline at end of file diff --git a/Source/68020/DitherCopyTo16Odd.a b/Source/68020/DitherCopyTo16Odd.a new file mode 100644 index 0000000..a10aaef --- /dev/null +++ b/Source/68020/DitherCopyTo16Odd.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; a0 = pointer to the 24-bit source pixmap row ; a1 = pointer to the 8-bit destination pixmap row ; a2 = pointer to the inverse color table ; a3 = pointer to the color table ; d0 = pointer to the even row dithering buffer ; d1 = pointer to the odd row dithering buffer ; d2 = pointer to the region buffer ; d7 = (low word) column count ; ; The following registers will be modified: ; ; d0,d1,d2,d3,d4,d5,d6,d7 ; a0,a1,a3 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = accumulator ; d2 = current sum of red components (<< 4) ; d3 = current sum of green components (<< 4) ; d4 = current sum of blue components (<< 4) ; d5 = (low word) ANDing mask = 0x0ff0 ; d5 = (high word) temporary storage for red error ; d6 = (low word) region column counter ; d6 = (high word) temporary storage for green error ; d7 = (low word) column counter ; d7 = (high word) temporary storage for blue error ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = pointer to inverse color table ; a3 = pointer to color table ; a4 = pointer to even dithering buffer ; a5 = pointer to odd dithering buffer ; a6 = pointer to region buffer ; movem.l a5/a6,-(sp) ;save a5/a6 on the stack move.l d0,a4 ;get the real a4 from d0 move.l d1,a5 ;and the real a5 from d1 move.l d2,a6 ;and the real a6 from d2 clr.l d1 ;clear d1 move.w d7,d1 ;copy the width to d1 adda.l d1,a1 ;add this to the destination ptr adda.l d1,a1 ;...twice for 16-bits move.l d1,d0 ;copy it to d0 lsl.l #2,d0 ;multiply by 4 adda.l d0,a0 ;and add to the source ptr add.l d1,d0 ;add it again = times 5 add.l d1,d0 ;once more = times 6 adda.l d0,a4 ;now point to the end of the even row adda.l d0,a5 ;and the end of the odd row move.w d7,d6 ;copy the width to d6 subq.w #1,d7 ;subtract 1 from the width for dbra move.w #4080,d5 ;use d5.l as a useful anding mask clr.w d2 ;clear the leftover dithering: red clr.w -2(a4) ;clear the even row dithering: blue clr.w d3 ;green clr.w -4(a4) ;green clr.w d4 ;blue clr.w -6(a4) ;red @ERgnLoop: cmp.w (a6)+,d6 ;have we found the end yet? bgt.s @ERgnLoop ;if not, loop beq.s @ERgnOn ;if equal, we're on at the end subq.w #2,a6 ;back up one word sub.w -(a6),d6 ;get region count in d6 bra.s @OddLoop ;if not zero, skip over this business @ERgnOn: subq.w #2,a6 ;back up one word move.w -(a6),d6 ;get previous value sub.w 2(a6),d6 ;subtract the next (larger) value bra.s @OddLoop ;start by updating the region ; ; Clamp over/underflows to 255/0 ; @FixRed: spl.b d2 ;if negative, set to 0, else set to ff lsl.w #4,d2 ;shift up 4 bits and.w d5,d2 ;and with d5 bra.s @RedRet ;return @FixGreen: spl.b d3 ;if negative, set to 0, else set to ff lsl.w #4,d3 ;shift up 4 bits and.w d5,d3 ;and with d5 bra.s @GreenRet ;return @FixBlue: spl.b d4 ;if negative, set to 0, else set to ff lsl.w #4,d4 ;shift up 4 bits and.w d5,d4 ;and with d5 bra.s @BlueRet ;return @OddLoop: swap d7 ;save the column counter ; ; First assemble the various parts: get the source pixel, add in the ; 7/16 error from the previous pixel, and then the errors from the ; previous row ; move.l -(a0),d1 ;get source pixel move.l d1,d0 ;copy to d0 add.w -(a5),d4 ;get dithering from previous row: blue lsl.l #4,d0 ;shift pixel value up by 4 and.w d5,d0 ;isolate the blue add.w d0,d4 ;add to the blue total add.w -(a5),d3 ;get dithering from previous row: green swap d0 ;get red part in lower 8 bits and.w d5,d0 ;keep only the good bits add.w d0,d2 ;add it to the leftover red add.w -(a5),d2 ;get dithering from previous row: red lsr.w #4,d1 ;shift pixel down by 4 (upper 8 bits << 4) and.w d5,d1 ;keep only the good bits add.w d1,d3 ;add it to the leftover green ; ; Round, check for overflows, and handle them ; addq.w #8,d2 ;add 1/2 a pixel to the total bftst d2{16:4} ;check bits 12-15 for red overflow bne.s @FixRed ;if it's set, fix up the red @RedRet: addq.w #8,d3 ;add 1/2 a pixel to the total bftst d3{16:4} ;check bits 12-15 for green overflow bne.s @FixGreen ;if it's set, fix up the green @GreenRet: addq.w #8,d4 ;add 1/2 a pixel to the total bftst d4{16:4} ;check bits 12-15 for blue overflow bne.s @FixBlue ;if it's set, fix up the blue @BlueRet: move.w d4,d0 ;get the blue bits in d0 ror.l #8,d0 ;rotate them off the right side ror.l #4,d0 ;(12 bits -- we do it in two steps) move.w d3,d0 ;get the green bits in d0 lsr.w #7,d0 ;shift off the low three bits ror.l #5,d0 ;rotate them off the right side move.w d2,d0 ;get the red bits in d0 lsr.w #7,d0 ;shift off the low three bits ror.l #6,d0 ;rotate off the right side swap d0 ;swap the result into the low word tst.w d6 ;is d6 negative? bmi.s @OddStore ;if so, store this value subq.w #2,a1 ;skip past the current pixel subq.w #1,d6 ;decrement this counter bne.s @OddCont ;if non-zero continue move.w -(a6),d6 ;get the next value sub.w 2(a6),d6 ;and subtract the next one bra.s @OddCont ;continue @OddStore: move.w d0,-(a1) ;store the value to the output addq.w #1,d6 ;increment the counter bne.s @OddCont ;if non-zero, continue sub.w -(a6),d6 ;subtract the next value add.w 2(a6),d6 ;and add the next @OddCont: move.w d2,d0 ;get red value in d0 lsr.w #7,d0 ;shift down 7 bits move.w d0,d1 ;copy to d1 lsl.w #5,d0 ;shift back 5 bits add.w d0,d1 ;add together lsl.w #2,d1 ;shift up two more sub.w d1,d2 ;subtract from desired red move.w d3,d0 ;get green value in d0 lsr.w #7,d0 ;shift down 7 bits move.w d0,d1 ;copy to d1 lsl.w #5,d0 ;shift back 5 bits add.w d0,d1 ;add together lsl.w #2,d1 ;shift up two more sub.w d1,d3 ;subtract from desired green move.w d4,d0 ;get blue value in d0 lsr.w #7,d0 ;shift down 7 bits move.w d0,d1 ;copy to d1 lsl.w #5,d0 ;shift back 5 bits add.w d0,d1 ;add together lsl.w #2,d1 ;shift up two more sub.w d1,d4 ;subtract from desired blue swap d5 ;save the 0x0ff0 mask swap d6 ;save region counter asr.w #4,d2 ;divide the error by 16: red asr.w #4,d3 ;green asr.w #4,d4 ;blue move.w d2,d5 ;copy this valueto d5-d7: red move.w d3,d6 ;green move.w d4,d7 ;blue add.w d5,d5 ;double it in d5-d7: red add.w d6,d6 ;green add.w d7,d7 ;blue movem.w d2-d4,-12(a4) ;store 1/16 at (-1,+1): red/green/blue add.w d5,d2 ;add 2 * error = 3/16: red add.w d6,d3 ;green add.w d7,d4 ;blue add.w d2, 0(a4) ;add 3/16 to (+1,+1): red add.w d5,d2 ;add 2 * error = 5/16: red add.w d3, 2(a4) ;green add.w d6,d3 ;green add.w d4, 4(a4) ;blue add.w d7,d4 ;blue add.w d4,-(a4) ;add 5/16 to (0,+1): blue add.w d5,d2 ;add 2 * error = 7/16: red add.w d3,-(a4) ;green add.w d6,d3 ;green add.w d2,-(a4) ;red add.w d7,d4 ;blue swap d6 ;restore region counter swap d5 ;restore 0x0ff0 mask swap d7 ;restore column counter dbra.w d7,@OddLoop ;loop until done movem.l (sp)+,a5/a6 ;restore a5 from the stack \ No newline at end of file diff --git a/Source/68020/DitherCopyTo8Even.a b/Source/68020/DitherCopyTo8Even.a new file mode 100644 index 0000000..918f875 --- /dev/null +++ b/Source/68020/DitherCopyTo8Even.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; a0 = pointer to the 24-bit source pixmap row ; a1 = pointer to the 8-bit destination pixmap row ; a2 = pointer to the inverse color table ; a3 = pointer to the color table ; d0 = pointer to the even row dithering buffer ; d1 = pointer to the odd row dithering buffer ; d2 = pointer to the region buffer ; d6 = pointer to the range-limit table ; d7 = (low word) column count ; ; The following registers will be modified: ; ; d0,d1,d2,d3,d4,d5,d6,d7 ; a0,a1,a3 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = accumulator ; d2 = current sum of red components (<< 4) ; d3 = current sum of green components (<< 4) ; d4 = current sum of blue components (<< 4) ; d5 = (low word) ANDing mask = 0x0ff0 ; d5 = (high word) temporary storage for red error ; d6 = (low word) region column counter ; d6 = (high word) temporary storage for green error ; d7 = (low word) column counter ; d7 = (high word) temporary storage for blue error ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = pointer to inverse color table ; a3 = pointer to color table ; a4 = pointer to even dithering buffer ; a5 = pointer to odd dithering buffer ; a6 = pointer to region buffer ; movem.l a5/a6,-(sp) ;save a5/a6 on the stack move.l d0,a4 ;get the real a4 from d0 move.l d1,a5 ;and the real a5 from d1 move.l d2,a6 ;and the real a6 from d2 ; ; Initialize our counters and clear out next row ; subq.w #1,d7 ;subtract 1 from the width for dbra swap d7 ;swap it high clr.w d3 ;clear the leftover dithering: red clr.w 0(a5) ;clear the odd row dithering: red clr.w d4 ;green clr.w 2(a5) ;green clr.w d5 ;blue clr.w 4(a5) ;blue ; ; Set up the region column counter in d7 ; move.w (a6)+,d7 ;get region start in d7 bne.s @EvenStart ;if not zero, skip over this business sub.w (a6)+,d7 ;otherwise, subtract the next word @EvenStart: swap d7 ;swap this information high exg.l a6,d6 ;point a6 to the range-limit table ; ; Begin main loop here ; @EvenLoop: swap d7 ;save the column counter ; ; Combine the accumulated errors and round to a pixel value ; add.w (a4)+,d3 ;add dithering from previous row: red addq.w #8,d3 ;round if necessary asr.w #4,d3 ;divide by 16 to get offset move.w 0(a6,d3.w*2),d3 ;range-limit this value add.w (a4)+,d4 ;add dithering from previous row: green addq.w #8,d4 ;round if necessary asr.w #4,d4 ;divide by 16 to get offset move.w 0(a6,d4.w*2),d4 ;range-limit this value add.w (a4)+,d5 ;add dithering from previous row: blue addq.w #8,d5 ;round if necessary asr.w #4,d5 ;divide by 16 to get offset move.w 0(a6,d5.w*2),d5 ;range-limit this value ; ; Offset the current pixel by the errors ; move.l (a0)+,d1 ;get source pixel in d1 move.w d1,d0 ;copy to d0 lsr.w #8,d0 ;shift to get the green add.w d0,d4 ;add to green total move.b d1,d0 ;get blue in d0 add.w d0,d5 ;add to blue total swap d1 ;swap words move.b d1,d0 ;get red in d0 add.w d0,d3 ;add to red total ; ; Check for overflows and handle them ; bftst d3{16:8} ;check bits 8-15 for red overflow beq.s @RedOK ;if okay, skip spl.b d3 ;otherwise, set to ff/00 andi.w #255,d3 ;clear out the upper bits @RedOK: bftst d4{16:8} ;check bits 8-15 for green overflow beq.s @GreenOK ;if okay, skip spl.b d4 ;otherwise, set to ff/00 andi.w #255,d4 ;clear out the upper bits @GreenOK: bftst d5{16:8} ;check bits 8-15 for blue overflow beq.s @BlueOK ;if okay, skip spl.b d5 ;otherwise, set to ff/00 andi.w #255,d5 ;clear out the upper bits @BlueOK: ; ; Get the inverse color table entry ; move.w d5,d0 ;get the blue bits in d0 ror.l #8,d0 ;rotate them off the right side move.w d4,d0 ;get the green bits in d0 lsr.w #3,d0 ;shift off the low three bits ror.l #5,d0 ;rotate them off the right side move.w d3,d0 ;get the red bits in d0 lsr.w #3,d0 ;shift off the low three bits ror.l #6,d0 ;rotate off the right side swap d0 ;swap the result into the low word clr.w d1 ;make sure the word in d1 is clear move.b 0(a2,d0.w),d1 ;get the inverse ctab entry in d1 ; ; Determine whether or not to draw this pixel, and handle switches ; tst.w d7 ;is d6 negative? bmi.s @EvenStore ;if so, store this value addq.w #1,a1 ;skip past the current pixel subq.w #1,d7 ;decrement this counter bne.s @EvenCont ;if non-zero continue exg.l d6,a6 ;swap table/region pointers sub.w (a6)+,d7 ;get the negative of the next value add.w -4(a6),d7 ;and add the previous one exg.l d6,a6 ;swap back bra.s @EvenCont ;continue @EvenStore: move.b d1,(a1)+ ;store the value to the output addq.w #1,d7 ;increment the counter bne.s @EvenCont ;if non-zero, continue exg.l d6,a6 ;swap table/region pointers move.w (a6)+,d7 ;get the next value sub.w -4(a6),d7 ;minus the previous exg.l d6,a6 ;swap back ; ; Get the real color for this entry ; @EvenCont: move.l 4(a3,d1.w*8),d0 ;get the green & blue components in d0 lsr.w #8,d0 ;shift 'em down sub.w d0,d5 ;subtract from the desired blue swap d0 ;get the green lsr.w #8,d0 ;shift 'em down sub.w d0,d4 ;subtract from the desired green move.w 2(a3,d1.w*8),d0 ;get the red comonent lsr.w #8,d0 ;shift down by 4 sub.w d0,d3 ;subtract from the desired red ; ; Divide the real color by 16 and set up to calculate odd multiples ; move.w d3,d0 ;copy error to d0-d2: red move.w d4,d1 ;green move.w d5,d2 ;blue add.w d0,d0 ;double it in d0-d2: red add.w d1,d1 ;green add.w d2,d2 ;blue ; ; Store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor ; movem.w d3-d5,6(a5) ;store 1/16 at (+1,+1): red/green/blue add.w d0,d3 ;add 2 * error = 3/16: red add.w d1,d4 ;green add.w d2,d5 ;blue add.w d3,-6(a5) ;add 3/16 to (-1,+1): red add.w d0,d3 ;add 2 * error = 5/16: red add.w d4,-4(a5) ;green add.w d1,d4 ;green add.w d5,-2(a5) ;blue add.w d2,d5 ;blue add.w d3,(a5)+ ;add 5/16 to (0,+1): red add.w d0,d3 ;add 2 * error = 7/16: red add.w d4,(a5)+ ;green add.w d1,d4 ;green add.w d5,(a5)+ ;blue add.w d2,d5 ;blue ; ; End of loop: go until done ; swap d7 ;restore column counter dbra.w d7,@EvenLoop ;loop until done movem.l (sp)+,a5/a6 ;restore a5/a6 from the stack \ No newline at end of file diff --git a/Source/68020/DitherCopyTo8Odd.a b/Source/68020/DitherCopyTo8Odd.a new file mode 100644 index 0000000..bc25623 --- /dev/null +++ b/Source/68020/DitherCopyTo8Odd.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; a0 = pointer to the 24-bit source pixmap row ; a1 = pointer to the 8-bit destination pixmap row ; a2 = pointer to the inverse color table ; a3 = pointer to the color table ; d0 = pointer to the even row dithering buffer ; d1 = pointer to the odd row dithering buffer ; d2 = pointer to the region buffer ; d6 = pointer to the range-limit table ; d7 = (low word) column count ; ; The following registers will be modified: ; ; d0,d1,d2,d3,d4,d5,d6,d7 ; a0,a1,a3 ; ; Internally, the register usage is as follows: ; ; d0 = accumulator ; d1 = accumulator ; d2 = current sum of red components (<< 4) ; d3 = current sum of green components (<< 4) ; d4 = current sum of blue components (<< 4) ; d5 = (low word) ANDing mask = 0x0ff0 ; d5 = (high word) temporary storage for red error ; d6 = (low word) region column counter ; d6 = (high word) temporary storage for green error ; d7 = (low word) column counter ; d7 = (high word) temporary storage for blue error ; ; a0 = pointer to 24-bit source row ; a1 = pointer to 8-bit destination row ; a2 = pointer to inverse color table ; a3 = pointer to color table ; a4 = pointer to even dithering buffer ; a5 = pointer to odd dithering buffer ; a6 = pointer to region buffer ; movem.l a5/a6,-(sp) ;save a5/a6 on the stack move.l d0,a4 ;get the real a4 from d0 move.l d1,a5 ;and the real a5 from d1 move.l d2,a6 ;and the real a6 from d2 ; ; Skip to the ends of everything here ; clr.l d1 ;clear d1 move.w d7,d1 ;copy the width to d1 adda.l d1,a1 ;add this to the destination ptr move.l d1,d0 ;copy it to d0 lsl.l #2,d0 ;multiply by 4 adda.l d0,a0 ;and add to the source ptr add.l d1,d0 ;add it again = times 5 add.l d1,d0 ;once more = times 6 adda.l d0,a4 ;now point to the end of the even row adda.l d0,a5 ;and the end of the odd row ; ; Initialize our counters and clear out next row ; move.w d7,d0 ;copy the width to d0 subq.w #1,d7 ;subtract 1 from the width for dbra swap d7 ;swap this info high move.w d0,d7 ;copy width back to lower word in d7 clr.w d3 ;clear the leftover dithering: red clr.w -2(a4) ;clear the even row dithering: blue clr.w d4 ;green clr.w -4(a4) ;green clr.w d5 ;blue clr.w -6(a4) ;red ; ; Set up the region column counter in d6 ; @ERgnLoop: cmp.w (a6)+,d7 ;have we found the end yet? bgt.s @ERgnLoop ;if not, loop beq.s @ERgnOn ;if equal, we're on at the end subq.w #2,a6 ;back up one word sub.w -(a6),d7 ;get region count in d6 bra.s @OddStart ;if not zero, skip over this business @ERgnOn: subq.w #2,a6 ;back up one word move.w -(a6),d7 ;get previous value sub.w 2(a6),d7 ;subtract the next (larger) value @OddStart: swap d7 ;swap this information high exg.l d6,a6 ;swap region/table pointers ; ; Begin main loop here ; @OddLoop: swap d7 ;save the column counter ; ; Combine the accumulated errors and round to a pixel value ; add.w -(a5),d5 ;add dithering from previous row: blue addq.w #8,d5 ;round if necessary asr.w #4,d5 ;divide by 16 to get offset move.w 0(a6,d5.w*2),d5 ;range-limit the error add.w -(a5),d4 ;add dithering from previous row: green addq.w #8,d4 ;round if necessary asr.w #4,d4 ;divide by 16 to get offset move.w 0(a6,d4.w*2),d4 ;range-limit the error add.w -(a5),d3 ;add dithering from previous row: red addq.w #8,d3 ;round if necessary asr.w #4,d3 ;divide by 16 to get offset move.w 0(a6,d3.w*2),d3 ;range-limit the error ; ; Offset the current pixel by the errors ; @ErrDone: move.l -(a0),d1 ;get source pixel in d1 move.w d1,d0 ;copy to d0 lsr.w #8,d0 ;shift to get the green add.w d0,d4 ;add to green total move.b d1,d0 ;get blue in d0 add.w d0,d5 ;add to blue total swap d1 ;swap words move.b d1,d0 ;get red in d0 add.w d0,d3 ;add to red total ; ; Check for overflows and handle them ; bftst d3{16:8} ;check bits 8-15 for red overflow beq.s @RedOK ;if okay, skip spl.b d3 ;otherwise, set to ff/00 andi.w #255,d3 ;clear out the upper bits @RedOK: bftst d4{16:8} ;check bits 8-15 for green overflow beq.s @GreenOK ;if okay, skip spl.b d4 ;otherwise, set to ff/00 andi.w #255,d4 ;clear out the upper bits @GreenOK: bftst d5{16:8} ;check bits 8-15 for blue overflow beq.s @BlueOK ;if okay, skip spl.b d5 ;otherwise, set to ff/00 andi.w #255,d5 ;clear out the upper bits @BlueOK: ; ; Get the inverse color table entry ; move.w d5,d0 ;get the blue bits in d0 ror.l #8,d0 ;rotate them off the right side move.w d4,d0 ;get the green bits in d0 lsr.w #3,d0 ;shift off the low three bits ror.l #5,d0 ;rotate them off the right side move.w d3,d0 ;get the red bits in d0 lsr.w #3,d0 ;shift off the low three bits ror.l #6,d0 ;rotate off the right side swap d0 ;swap the result into the low word clr.w d1 ;make sure the word in d1 is clear move.b 0(a2,d0.w),d1 ;get the inverse ctab entry in d1 ; ; Determine whether or not to draw this pixel, and handle switches ; tst.w d7 ;is d7 negative? bmi.s @OddStore ;if so, store this value subq.w #1,a1 ;skip past the current pixel subq.w #1,d7 ;decrement this counter bne.s @OddCont ;if non-zero continue exg.l a6,d6 ;swap region/table pointers move.w -(a6),d7 ;get the next value sub.w 2(a6),d7 ;and subtract the next one exg.l a6,d6 ;swap back bra.s @OddCont ;continue @OddStore: move.b d1,-(a1) ;store the value to the output addq.w #1,d7 ;increment the counter bne.s @OddCont ;if non-zero, continue exg.l a6,d6 ;swap region/table pointers sub.w -(a6),d7 ;subtract the next value add.w 2(a6),d7 ;and add the next exg.l a6,d6 ;swap back ; ; Get the real color for this entry ; @OddCont: move.l 4(a3,d1.w*8),d0 ;get the green & blue components in d0 lsr.w #8,d0 ;shift 'em down sub.w d0,d5 ;subtract from the desired blue swap d0 ;get the green lsr.w #8,d0 ;shift 'em down sub.w d0,d4 ;subtract from the desired green move.w 2(a3,d1.w*8),d0 ;get the red comonent lsr.w #8,d0 ;shift down by 4 sub.w d0,d3 ;subtract from the desired red ; ; Divide the real color by 16 and set up to calculate odd multiples ; move.w d3,d0 ;copy error to d0-d2: red move.w d4,d1 ;green move.w d5,d2 ;blue add.w d0,d0 ;double it in d0-d2: red add.w d1,d1 ;green add.w d2,d2 ;blue ; ; Store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor ; movem.w d3-d5,-12(a4) ;store 1/16 at (-1,+1): red/green/blue add.w d0,d3 ;add 2 * error = 3/16: red add.w d1,d4 ;green add.w d2,d5 ;blue add.w d3, 0(a4) ;add 3/16 to (+1,+1): red add.w d0,d3 ;add 2 * error = 5/16: red add.w d4, 2(a4) ;green add.w d1,d4 ;green add.w d5, 4(a4) ;blue add.w d2,d5 ;blue add.w d5,-(a4) ;add 5/16 to (0,+1): blue add.w d2,d5 ;add 2 * error = 7/16: blue add.w d4,-(a4) ;green add.w d1,d4 ;green add.w d3,-(a4) ;red add.w d0,d3 ;red ; ; End of loop: go until done ; swap d7 ;restore column counter dbra.w d7,@OddLoop ;loop until done movem.l (sp)+,a5/a6 ;restore a5 from the stack \ No newline at end of file diff --git a/Source/68020/FillHistogram16.a b/Source/68020/FillHistogram16.a new file mode 100644 index 0000000..be1a8cd --- /dev/null +++ b/Source/68020/FillHistogram16.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ movem.l d3/d4/a6,-(sp) ;Save our registers move.l 20(sp),a6 ;Get the address of the FillData structure in a6 ;(based off stack: 3 registers + 1 a6 link + 1 return ; = 5 * 4 = 20 bytes) move.l #32767,d3 ;AND mask for this pixel (32767 = $7fff) movea.l baseAdr(a6),a0 ;Get the starting address in a0 movea.l histogram(a6),a1 ;Point a1 to our histogram @RLoop16: move.l a0,-(sp) ;Push the address on the stack move.l width(a6),d4 ;Get the width counter subq.l #1,d4 ;Minus one @CLoop16: move.w (a0)+,d0 ;Get the colors in d0 and.l d3,d0 ;Clear out the alpha bit addq.w #1,(0,a1,d0.l*2) ;Increment the histogram beq.s @RZero16 ;Fix this if it's zero dbra.w d4,@CLoop16 ;Continue the loop over all columns bra.s @Skip16 ;Skip over the RZero part @RZero16: subq.w #1,(0,a1,d0.l*2) ;Put it back to 0xffff dbra.w d4,@CLoop16 ;Loop over the remaining columns @Skip16: movea.l (sp)+,a0 ;Return to the beginning of the row adda.l rowBytes(a6),a0 ;Go to the next row subq.l #1,height(a6) ;Decrement the height bne.s @RLoop16 ;If non-zero, branch movem.l (sp)+,d3/d4/a6 ;Restore our registers \ No newline at end of file diff --git a/Source/68020/FillHistogram32.a b/Source/68020/FillHistogram32.a new file mode 100644 index 0000000..8761ab6 --- /dev/null +++ b/Source/68020/FillHistogram32.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ movem.l d3-d6/a6,-(sp) ;Save our registers move.l 28(sp),a6 ;Get the address of the FillData structure in a6 ;(based off stack: 5 registers + 1 a6 link + 1 return ; = 7 * 4 = 28 bytes) move.l #31744,d5 ;AND mask for red part (31744 == $7c00) move.l #992,d4 ; for green part (992 = $3e00) move.l #31,d3 ; for blue part (31 == $001f) movea.l baseAdr(a6),a0 ;Get the starting address in a0 movea.l histogram(a6),a1 ;Point a1 to our histogram @RLoop32: move.l a0,-(sp) ;Push the address on the stack move.l width(a6),d6 ;Get the width counter subq.l #1,d6 ;Minus one @CLoop32: move.l (a0)+,d0 ;Get the colors in d0 move.l d0,d1 ;Copy this to d1 move.l d0,d2 ;And to d2 lsr.l #3,d0 ;Get the blue bits in place and.l d3,d0 ;Kill off all except the blue lsr.l #6,d1 ;Get the green bits in place and.l d4,d1 ;Kill off the others add.l d1,d0 ;Add in the green moveq.l #9,d1 ;Get the shift count in d1 lsr.l d1,d2 ;Get the red bits in place and.l d5,d2 ;Kill off the other bits add.l d2,d0 ;Add that in as well addq.w #1,(0,a1,d0.l*2) ;Increment the histogram beq.s @RZero32 ;Fix this if it's zero dbra.w d6,@CLoop32 ;Continue the loop over all columns bra.s @Skip32 ;Skip over the RZero part @RZero32: subq.w #1,(0,a1,d0.l*2) ;Put it back to 0xffff dbra.w d6,@CLoop32 ;Loop over the remaining columns @Skip32: movea.l (sp)+,a0 ;Return to the beginning of the row adda.l rowBytes(a6),a0 ;Go to the next row subq.l #1,height(a6) ;Decrement the height bne.s @RLoop32 ;If non-zero, branch movem.l (sp)+,d3-d6/a6 ;Restore our registers \ No newline at end of file diff --git a/Source/68020/GIF.a b/Source/68020/GIF.a new file mode 100644 index 0000000..0910038 --- /dev/null +++ b/Source/68020/GIF.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ machine mc68020 src equ 0 dest equ 4 stack equ 8 theEnd equ 12 tree equ 16 store equ 20 charSize equ 68 width equ 70 theReturn equ 72 ; ; void DoDecodeRow(GIFData theData) ; DoDecodeRow proc export link a6,#0 include 'DecodeRow.a' unlk a6 rts endp ; ; void DoDecodeDummyRow(GIFData theData) ; DoDecodeDummyRow proc export link a6,#0 include 'DecodeDummyRow.a' unlk a6 rts endp end \ No newline at end of file diff --git a/Source/68020/InitRegion.a b/Source/68020/InitRegion.a new file mode 100644 index 0000000..3f030f8 --- /dev/null +++ b/Source/68020/InitRegion.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; a0 = pointer to the current region definition ; a1 = pointer to rgnBuffer[0] ; d2 = boxRect.top ; d3 = boxRect.left ; d4 = height ; d5 = width ; ; The following registers will be modified: ; ; d0,d1 ; a0,a1 ; move.l a2,-(sp) ;save a2 on the stack move.l a1,a2 ;copy a1 there ; ; Check for a rectangular region ; move.l (a0),a0 ;deference a0 cmpi.w #10,(a0)+ ;is this a rectangular region? beq.s @RectRgn ;if so, set that up ; ; Region is non-rectangular; set up the first scan line buffer ; addq.w #8,a0 ;skip over rectangle move.w (a0)+,d0 ;get Y coordinate sub.w d2,d0 ;offset it from the top move.w d0,(a1)+ ;store this as a count in Y clr.w (a1)+ ;zero out the next word tst.w d0 ;is the first row included? bne.s @RgnCont ;if not, proceed from here @CopyFirst: move.w (a0)+,d0 ;get X coordinate cmpi.w #32767,d0 ;are we done? (32767 = $7fff) beq.s @CopyFDone ;if so, skip ahead sub.w d3,d0 ;offset it from the left move.w d0,(a1)+ ;store it bra.s @CopyFirst ;loop until done @CopyFDone: move.w (a0)+,d0 ;get next Y coordinate sub.w d2,d0 ;offset it from the top move.w d0,(a2) ;store it as the first word bra.s @RgnCont ;continue onwards ; ; Set up a rectangular region; fill in a fake buffer ; @RectRgn: move.w d4,(a1)+ ;row count = height clr.w (a1)+ ;zero out the next word clr.w (a1)+ ;left side is zero move.w d5,(a1)+ ;right side is width ; ; Terminate the buffer and save our position ; @RgnCont: move.w #32767,(a1)+ ;store the terminator (32767 = $7fff) move.l (sp)+,a2 ;restore a2 from the stack \ No newline at end of file diff --git a/Source/68020/QDxDispatchPatch.a b/Source/68020/QDxDispatchPatch.a new file mode 100644 index 0000000..c9de6cc --- /dev/null +++ b/Source/68020/QDxDispatchPatch.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ machine mc68020 include 'Traps.a' include 'SysEqu.a' ; Note that all parameters are offset 24: ; 4 bytes for return address from trap ; 20 bytes for saved registers ; ; So: ; 24(sp) = flags ; 28(sp) = device handle ; 32(sp) = color table handle ; 36(sp) = rectangle ; 40(sp) = depth ; 42(sp) = pointer to destination gworld ; 46(sp) = result code useTempMem equ 4 memFullErr equ -108 QDxDispatchPatch proc export OnOffSwitch dc.w 0 RoundGWorld dc.w 0 OriginalTrap dc.l 0 tst.w d0 ;is this a NewGWorld call? bne.s @DontBother ;if not, skip all this fun tst.w OnOffSwitch(pc) ;are we on or off? beq.s @DontBother ;if off, skip all this movem.l d0-d2/a0/a1,-(sp) ;save registers on the stack move.l 24(sp),d0 ;get flags in d0 andi.b #useTempMem,d0 ;isolate the temp mem bit beq.s @PopAndDontBother ;if not on, skip entirely movea.l 36(sp),a0 ;get address of rectangle in a0 move.w 4(a0),d0 ;get bottom sub.w (a0),d0 ;minus top in d0 move.w 6(a0),d1 ;get right sub.w 2(a0),d1 ;minus left in d1 mulu.w d1,d0 ;times each other moveq.l #0,d1 ;clear out d1 move.w 40(sp),d1 ;get depth in d1 bne.s @NotZeroDepth ;if non-zero, skip ahead moveq.l #32,d1 ;otherwise, assume worst-case (32) @NotZeroDepth: cmpi.w #32,d1 ;above 32? ble.s @GoAhead ;if not, skip subi.w #32,d1 ;subtract 32 (since it's grayscale) @GoAhead: mulu.l d1,d0 ;get depth * height * width lsr.l #3,d0 ;divide by 8 cmpi.l #$00080000,d0 ;less than 512k? blt.s @AdjustGWorldSize ;if so, let it happen, but round to 16 pixels move.w #memFullErr,46(sp) ;store an error movea.l 42(sp),a0 ;get address of gworldptr clr.l (a0) ;zero the result movem.l (a7)+,d0-d2/a0/a1 ;restore our registers movea.l (a7)+,a1 ;get return address in a1 adda.w #$16,sp ;pop off parameters from stack jmp (a1) ;return to caller @AdjustGWorldSize: tst.w RoundGWorld(pc) ;should we round to nearest 16 pixels? beq.s @PopAndDontBother ;if not, skip move.w 4(a0),d0 ;get bottom of rect addi.w #15,d0 ;add 15 andi.w #$fff0,d0 ;round to the nearest 16 pixels move.w d0,4(a0) ;store this as new bottom @PopAndDontBother: movem.l (a7)+,d0-d2/a0/a1 ;restore our registers @DontBother: move.l OriginalTrap(pc),-(a7);push original address on stack rts ;jump there ; andi.l #$ffffffff-useTempMem,4(sp) ;clear the useTempMem bit ; lea OldZone(pc),a0 ;point a0 to our old zone storage ; move.l TheZone,(a0) ;save the old zone in a0 ; move.l ApplZone,a0 ;get the application zone in a0 ; _SetZone ;and set it now ; move.l d0,-(sp) ;save d0 on the stack ; move.l #$00018000,d0 ;get 96k in d0 ; _PurgeMem ;purge enough memory to get that size ; _MaxBlock ;now get largest contig block ; cmpi.l #$00018000,d0 ;is it more than 96k? ; bge.s @SetTo64k ;if so, clamp to 64k ; moveq.l #0,a0 ;otherwise, zero out the "handle" ; ori.l #useTempMem,8(sp) ;turn the temp mem flag back on ; bra.s @DontAllocate ;and skip over the allocation ;@SetTo64k: ; move.l #$00010000,d0 ;set value to 64k ; _NewHandle ;get a new handle of that size ;@DontAllocate: ; move.l a0,d0 ;copy handle to d0 ; lea TempHandle(pc),a0 ;get the address of the temp handle storage ; move.l d0,(a0) ;store the new handle there ; move.l (sp)+,d0 ;restore d0 and a0 ; lea OrigReturn(pc),a0 ;point a0 to our local storage ; move.l (sp)+,(a0) ;and get original return address ; move.l OriginalTrap(pc),a0 ;get original trap address ; jsr (a0) ;branch to the subroutine ; move.l TempHandle(pc),a0 ;get the temp handle back ; tst.l a0 ;is it nil? ; beq.s @DontDispose ;if something went wrong, don't dispose ; _DisposHandle ;otherwise, get rid of the handle ;@DontDispose: ; move.l OldZone(pc),a0 ;get old zone in a0 ; _SetZone ;make sure we point back to it ; move.l OrigReturn(pc),a0 ;get original return address ; jmp (a0) ;and jmp there ; ;@DontBother: ; move.l OriginalTrap(pc),-(sp);store the return address on the stack ; rts ;and return there ;TempHandle dc.l 0 ;OrigReturn dc.l 0 ;OldZone dc.l 0 endp end \ No newline at end of file diff --git a/Source/68020/Quantize.a b/Source/68020/Quantize.a new file mode 100644 index 0000000..1bee08b --- /dev/null +++ b/Source/68020/Quantize.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ machine mc68020 ; ; Offsets of the various parameters in FillData ; height equ 0 width equ 4 rowBytes equ 8 histogram equ 12 baseAdr equ 16 ; ; void DoFillHistogram32(FillDataPtr theData) ; DoFillHistogram32 proc export link a6,#0 include 'FillHistogram32.a' unlk a6 rts endp ; ; void DoFillHistogram16(FillDataPtr theData) ; DoFillHistogram16 proc export link a6,#0 include 'FillHistogram16.a' unlk a6 rts endp end \ No newline at end of file diff --git a/Source/68020/UpdateRegion.a b/Source/68020/UpdateRegion.a new file mode 100644 index 0000000..e9cf4fc --- /dev/null +++ b/Source/68020/UpdateRegion.a @@ -0,0 +1 @@ +;*********************************************************/ ;* This source code copyright (c) 1991-2001, Aaron Giles */ ;* See the Read Me file for licensing information. */ ;* Contact email: mac@aarongiles.com */ ;*********************************************************/ ; ; On entry here we expect the following values: ; ; a0 = pointer to the current region definition ; a1 = pointer to rgnBuffer[2] ; d0 = boxRect.left ; ; The following registers will be modified: ; ; d0,d1 ; a0,a1 ; movem.l a2/d2,-(sp) ;save a2/d2 on the stack move.l a1,a2 ;copy a1 to a2 subq.l #4,a2 ;point a2 to rgnBuffer[0] move.w d0,d2 ;copy boxRect.left to d2 move.w -2(a0),d1 ;get last Y coordinate ; ; The region definition has changed: set up to add/delete elements as necessary ; @URgnLoop: move.w (a0)+,d0 ;get next X coordinate cmpi.w #32767,d0 ;end of list? (32767 == $7fff) bne.s @ScanRgn ;if not, skip ahead move.w (a0)+,d0 ;get next Y sub.w d1,d0 ;minus the old Y move.w d0,(a2) ;store it in the rgnBuffer movem.l (sp)+,a2/d2 ;restore a2/d2 from the stack bra.s @TheEnd ;return @ScanRgn: sub.w d2,d0 ;offset X by left side @SRgnLoop: cmp.w (a1)+,d0 ;compare to our buffer beq.s @DeleteRgn ;if equal, they cancel bgt.s @SRgnLoop ;if greater, keep looking ; ; Insert an element into our region buffer ; move.l a1,-(sp) ;save a1 subq.l #2,a1 ;decrement a1 back one word swap d0 ;swap d0 high @IRgnLoop: move.w (a1),d0 ;get next word swap d0 ;swap it high move.w d0,(a1)+ ;store the old word cmpi.w #32767,d0 ;done? (32767 == $7fff) bne.s @IRgnLoop ;if not, loop move.l (sp)+,a1 ;restore a1 bra.s @URgnLoop ;loop for some more ; ; Delete an element from our region buffer ; @DeleteRgn: move.l a1,-(sp) ;save a1 @DRgnLoop: move.w (a1)+,d0 ;get this value move.w d0,-4(a1) ;store it back one cmpi.w #32767,d0 ;done? (32767 == $7fff) bne.s @DRgnLoop ;if not, loop move.l (sp)+,a1 ;restore a1 subq.l #2,a1 ;point back one word bra.s @URgnLoop ;loop for some more @TheEnd: \ No newline at end of file diff --git a/Source/C/AppleEventUtils.c b/Source/C/AppleEventUtils.c new file mode 100644 index 0000000..1f59ced --- /dev/null +++ b/Source/C/AppleEventUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local structures: * eventList, eventListPtr = structure containing event handlers to install * objectList, objectListPtr = structure containing object accessors to install * */ #if THINK_C extern pascal OSErr AEObjectInit(void); #endif typedef struct { AEEventClass evclass; AEEventID evid; void *handler; long refcon; } eventList, *eventListPtr; typedef struct { DescType evclass; DescType container; void *handler; } objectList, *objectListPtr; /* * AppleEventInit() * * Purpose: Installs AppleEvent handlers for the AppleEvents we support * Inputs: none * Returns: nothing * */ void AppleEventInit(void) { eventList theEventList[] = { { kCoreEventClass, kAEOpenApplication, HandleOpenApplication, 0 }, { kCoreEventClass, kAEOpenDocuments, HandleOpenDocuments, 0 }, { kCoreEventClass, kAEPrintDocuments, HandlePrintDocuments, 0 }, { kCoreEventClass, kAEQuitApplication, HandleQuitApplication, 0 }, { kAECoreSuite, kAEClone, HandleClone, 0 }, { kAECoreSuite, kAEClose, HandleClose, 0 }, { kAECoreSuite, kAECountElements, HandleCountElements, 0 }, { kAECoreSuite, kAECreateElement, HandleCreateElement, 0 }, { kAECoreSuite, kAEDelete, HandleDelete, 0 }, { kAECoreSuite, kAEDoObjectsExist, HandleDoObjectsExist, 0 }, { kAECoreSuite, kAEGetData, HandleGetData, 0 }, { kAECoreSuite, kAEGetDataSize, HandleGetDataSize, 0 }, { kAECoreSuite, kAEMove, HandleMove, 0 }, { kAECoreSuite, kAESave, HandleSave, 0 }, { kAECoreSuite, kAESetData, HandleSetData, 0 }, { kAEMiscStandards, kAECopy, HandleCopy, 0 }, { kJPEGViewSuite, kAEQuantizeImage, HandleQuantize, 0 }, { kJPEGViewSuite, kAESlideShow, HandleSlideShow, 0 }, { 0, 0, nil, 0 } }; objectList theObjectList[] = { { cWindow, typeNull, WindowAccessor }, { cWindow, cWindow, WindowAccessor }, { cDocument, typeNull, DocumentAccessor }, { cDocument, cWindow, DocumentAccessor }, { cDocument, cDocument, DocumentAccessor }, { cFile, cDocument, FileAccessor }, { cFile, cFile, FileAccessor }, { cDrawingArea, cWindow, DrawingAreaAccessor }, { cDrawingArea, cDrawingArea, DrawingAreaAccessor }, { cImage, cDocument, ImageAccessor }, { cImage, cDrawingArea, ImageAccessor }, { cImage, cImage, ImageAccessor }, { cPixelMap, cImage, PixelMapAccessor }, { cPixelMap, cPixelMap, PixelMapAccessor }, { typeProperty, typeNull, AppPropertyAccessor }, { typeProperty, cWindow, WinPropertyAccessor }, { typeProperty, cDocument, DocPropertyAccessor }, { typeProperty, cFile, FilePropertyAccessor }, { typeProperty, cDrawingArea, DrawPropertyAccessor }, { typeProperty, cImage, ImagePropertyAccessor }, { typeProperty, cPixelMap, PixelPropertyAccessor }, { typeProperty, cSelection, SelPropertyAccessor }, { 0, 0, nil } }; eventListPtr theEvent; objectListPtr theObject; if ((Ptr)AEObjectInit == kUnresolvedSymbolAddress) { gFoundOSL = false; theEventList[4].handler = nil; } for (theEvent = theEventList; theEvent->handler; theEvent++) if (AEInstallEventHandler(theEvent->evclass, theEvent->evid, NewAEEventHandlerProc((ProcPtr)theEvent->handler), theEvent->refcon, 0) != noErr) FatalError(errNoAppleEvents); if (!gFoundOSL) return; if (AEObjectInit() != noErr) FatalError(errNoAppleEvents); for (theObject = theObjectList; theObject->handler; theObject++) if (AEInstallObjectAccessor(theObject->evclass, theObject->container, NewOSLAccessorProc((ProcPtr)theObject->handler), 0, false) != noErr) FatalError(errNoAppleEvents); AEInstallCoercionHandler(typeIntlText, typeChar, (AECoercionHandlerUPP)NewAECoercePtrProc((ProcPtr)AECoerceIntlToChar), 0, false, false); AEInstallCoercionHandler(typeQDRectangle, typeAEList, (AECoercionHandlerUPP)NewAECoercePtrProc((ProcPtr)AECoerceRectToList), 0, false, false); AEInstallCoercionHandler(typeAEList, typeQDRectangle, (AECoercionHandlerUPP)NewAECoerceDescProc((ProcPtr)AECoerceListToRect), 0, true, false); } /* * HandleUnsupportedEvent() * * Purpose: Dummy event handler for unsupported AppleEvents * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation * (i.e., errAEEventNotHandled) * */ pascal OSErr HandleUnsupportedEvent(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(theEvent, reply, refCon) #endif return errAEEventNotHandled; } /* * AENewEvent(theEvent, theClass, theID) * * Purpose: Creates a new AppleEvent, directed toward the current application * Inputs: theEvent = a pointer to an AppleEvent record * theClass = the event class of the event * theID = the event ID of the event * Returns: an OSErr describing what went wrong * */ OSErr AENewEvent(AppleEvent *theEvent, AEEventClass theClass, AEEventID theID) { ProcessSerialNumber theProcess = { 0, kCurrentProcess }; AEDesc theDesc; OSErr theErr; theErr = AECreateDesc(typeProcessSerialNumber, (void *)&theProcess, sizeof(ProcessSerialNumber), &theDesc); if (theErr == noErr) { theErr = AECreateAppleEvent(theClass, theID, &theDesc, kAutoGenerateReturnID, kAnyTransactionID, theEvent); AEDisposeDesc(&theDesc); } return theErr; } /* * AEMakeIntlDesc(theString, theDesc) * * Purpose: Creates a typeIntlText descriptor from the given string * Inputs: theString = the source string * theDesc = a pointer to the descriptor to put the record into * Returns: an OSErr describing what went wrong * */ OSErr AEMakeIntlDesc(StringPtr theString, AEDesc *theDesc) { struct { short script; short language; char text[256]; } theIText; theIText.script = smCurrentScript; theIText.language = currentCurLang; BlockMove(&theString[1], theIText.text, theString[0]); return AECreateDesc(typeIntlText, (void *)&theIText, 4 + theString[0], theDesc); } /* * AEMakeBeginningILoc(theDesc) * * Purpose: Creates an insertionLoc record pointing to the beginning of the null * container * Inputs: theDesc = a pointer to the descriptor to put the record into * floating = flag: true if this is a floating window * Returns: an OSErr describing what went wrong * */ OSErr AEMakeBeginningILoc(AEDesc *theDesc, Boolean floating) { AEDesc theContainer, theRecord; DescType beginning; OSErr theErr; theErr = AECreateList(nil, 0, true, &theRecord); if (theErr == noErr) { if (GetFirstWindow()) { theErr = MakeWindowObject(floating ? GetFirstWindow() : FWFrontWindow(), &theContainer); beginning = kAEBefore; } else { theContainer.descriptorType = typeNull; theContainer.dataHandle = nil; beginning = kAEBeginning; } if (theErr == noErr) { theErr = AEPutParamDesc(&theRecord, keyAEObject, &theContainer); if (theContainer.descriptorType != typeNull) AEDisposeDesc(&theContainer); } if (theErr == noErr) theErr = AEAddEnumerated(&theRecord, keyAEPosition, &beginning); if (theErr == noErr) theErr = AECoerceDesc(&theRecord, typeInsertionLoc, theDesc); AEDisposeDesc(&theRecord); } return theErr; } /* * AECreateHandleDesc(theType, theHandle, theDesc) * * Purpose: Creates a descriptor record based on a handle * Inputs: theType = the type to create * theHandle = the handle * theDesc = a pointer to the descriptor to put the record into * Returns: an OSErr describing what went wrong * */ OSErr AECreateHandleDesc(DescType theType, Handle theHandle, AEDesc *theDesc) { char hState = HGetState(theHandle); OSErr theErr; HLock(theHandle); theErr = AECreateDesc(theType, (void *)*theHandle, GetHandleSize(theHandle), theDesc); HSetState(theHandle, hState); return theErr; } /* * AEAddAlias(theEvent, theKey, theSpec) * * Purpose: Creates an alias descriptor from an FSSpec and adds it to the given * event under the given keyword * Inputs: theEvent = a pointer to the AppleEvent record * theKey = the keyword identifying this parameter * theSpec = the file system specification for the file * Returns: an OSErr describing what went wrong * */ OSErr AEAddAlias(AppleEvent *theEvent, AEKeyword theKey, FSSpec *theSpec) { AliasHandle theAlias; AEDesc theDesc; OSErr theErr; theErr = NewAlias(nil, theSpec, &theAlias); if (theErr == noErr) { HLock((Handle)theAlias); theErr = AECreateDesc(typeAlias, (void *)*theAlias, GetHandleSize((Handle)theAlias), &theDesc); DisposeHandle((Handle)theAlias); if (theErr == noErr) { theErr = AEPutParamDesc(theEvent, theKey, &theDesc); AEDisposeDesc(&theDesc); } } return theErr; } /* * AEAddAliasList(theEvent, theKey, theSpec, count) * * Purpose: Creates an alias list descriptor from an array of FSSpecs and adds it * to the given event under the given keyword * Inputs: theEvent = a pointer to the AppleEvent record * theKey = the keyword identifying this parameter * theSpec = pointer to an array of file system specifications * count = the number of entries in the above array * Returns: an OSErr describing what went wrong * */ OSErr AEAddAliasList(AppleEvent *theEvent, AEKeyword theKey, FSSpec *theSpec, short count) { AliasHandle theAlias; AEDescList theList; AEDesc theDesc; OSErr theErr; short i; theErr = AECreateList(nil, 0, false, &theList); if (theErr == noErr) { for (i = 0; (theErr == noErr) && (i < count); i++) { theErr = NewAlias(nil, theSpec++, &theAlias); if (theErr == noErr) { HLock((Handle)theAlias); theErr = AECreateDesc(typeAlias, (void *)*theAlias, GetHandleSize((Handle)theAlias), &theDesc); HUnlock((Handle)theAlias); if (theErr == noErr) { theErr = AEPutDesc(&theList, i + 1, &theDesc); AEDisposeDesc(&theDesc); } DisposeHandle((Handle)theAlias); } } if (theErr == noErr) theErr = AEPutParamDesc(theEvent, theKey, &theList); AEDisposeDesc(&theList); } return theErr; } /* * AEExtractObject(theEvent, theKey, theToken) * * Purpose: Extracts a parameter of typeObjectSpecifier from the given event * Inputs: theEvent = a pointer to the AppleEvent record * theKey = the keyword identifying this parameter, or 0 if theEvent is * actually a simple descriptor containing the parameter * theToken = pointer to a destination location to store the result * Returns: an OSErr describing what went wrong * */ OSErr AEExtractObject(AppleEvent *theEvent, AEKeyword theKey, AEDesc *theToken) { AEDesc coercedDesc, theDesc; OSErr theErr = noErr; if (theKey) theErr = AEGetParamDesc(theEvent, theKey, typeWildCard, &theDesc); else theErr = AEDuplicateDesc(theEvent, &theDesc); if (theErr == noErr) { if (theDesc.descriptorType == typeNull) { theToken->descriptorType = typeNull; theToken->dataHandle = nil; AEDisposeDesc(&theDesc); return noErr; } else if (theDesc.descriptorType != typeObjectSpecifier) theErr = AECoerceDesc(&theDesc, typeObjectSpecifier, &coercedDesc); else theErr = AEDuplicateDesc(&theDesc, &coercedDesc); AEDisposeDesc(&theDesc); if (theErr == noErr) { theErr = AEResolve(&coercedDesc, kAEIDoMinimum, theToken); AEDisposeDesc(&coercedDesc); } } return theErr; } /* * AEExtractInsertionLoc(theEvent, theKey, theWindow) * * Purpose: Extracts a parameter of typeInsertionLoc from the given event * Inputs: theEvent = a pointer to the AppleEvent record * theKey = the keyword identifying this parameter, or 0 if theEvent is * actually a simple descriptor containing the parameter * theWindow = pointer to a WindowPtr behind which we should put a new window * Returns: an OSErr describing what went wrong * */ OSErr AEExtractInsertionLoc(AppleEvent *theEvent, AEKeyword theKey, WindowPtr *theWindow) { AEDesc coercedDesc, theObject; ObjectTokenHandle theToken; OSErr theErr = noErr; DescType position; WindowPtr window; if (theKey) theErr = AEGetParamDesc(theEvent, theKey, typeAERecord, &coercedDesc); else { if (theEvent->descriptorType != typeAERecord) theErr = AECoerceDesc(theEvent, typeAERecord, &coercedDesc); else theErr = AEDuplicateDesc(theEvent, &coercedDesc); } if (theErr == noErr) { theErr = AEExtractObject(&coercedDesc, keyAEObject, &theObject); if (theErr == noErr) { theErr = AEExtractEnumerated(&coercedDesc, keyAEPosition, &position); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if ((theObject.descriptorType == typeNull) || ((*theToken)->count == 1)) { if (theObject.descriptorType != typeNull) { *theWindow = (WindowPtr)(*theToken)->object[0]; for (window = GetFirstWindow(); window && (window != *theWindow); window = NextWindow(window)); } else window = GetFirstWindow(); switch (position) { case kAEBefore: if ((theObject.descriptorType == cWindow) || (theObject.descriptorType == cDocument)) { if (GetFirstWindow() == *theWindow) *theWindow = nil; else { for (window = GetFirstWindow(); window && (NextWindow(window) != *theWindow); window = NextWindow(window)); *theWindow = window; } } else theErr = errAEEventFailed; break; case kAEAfter: if ((theObject.descriptorType == cWindow) || (theObject.descriptorType == cDocument)) break; else theErr = errAEEventFailed; break; case kAEBeginning: if (theObject.descriptorType == typeNull) *theWindow = nil; else theErr = errAEEventFailed; break; case kAEEnd: if (theObject.descriptorType == typeNull) { if (!GetFirstWindow()) *theWindow = nil; else { for (window = GetFirstWindow(); NextWindow(window); window = NextWindow(window)); *theWindow = window; } } else theErr = errAEEventFailed; break; case kAEReplace: for (window = GetFirstWindow(); window && (NextWindow(window) != *theWindow); window = NextWindow(window)); theErr = DoCloseWindow(*theWindow, gThePrefs.restoreColors); if (theErr == noErr) *theWindow = (WindowPtr)window; break; } } else theErr = errAENotASingleObject; } AEDisposeDesc(&theObject); } AEDisposeDesc(&coercedDesc); } return theErr; } /* * AEExtractGeneric(theEvent, theKey, theType, theSize, theData) * * Purpose: Extracts a parameter of typeLongInteger from the given event * Inputs: theEvent = a pointer to the AppleEvent record * theKey = the keyword identifying this parameter, or 0 if theEvent is * actually a simple descriptor containing the parameter * theType = the type we want * theSize = the size of our data * theData = pointer to a destination location to store the result * Returns: an OSErr describing what went wrong * */ OSErr AEExtractGeneric(AppleEvent *theEvent, AEKeyword theKey, DescType theType, Size theSize, void *theData) { OSErr theErr = noErr; DescType actualType; AEDesc coercedDesc; long actualSize; if (theKey) theErr = AEGetParamPtr(theEvent, theKey, theType, &actualType, theData, theSize, &actualSize); else { if (theEvent->descriptorType != theType) theErr = AECoerceDesc(theEvent, theType, &coercedDesc); else theErr = AEDuplicateDesc(theEvent, &coercedDesc); if (theErr == noErr) { actualSize = GetHandleSize(coercedDesc.dataHandle); if (theSize > actualSize) theSize = actualSize; HLock(coercedDesc.dataHandle); BlockMove(*coercedDesc.dataHandle, theData, theSize); AEDisposeDesc(&coercedDesc); } } return theErr; } /* * AEExtractTypeList(theEvent, theKey, theData) * * Purpose: Extracts a list of typeType records from the given event * Inputs: theEvent = a pointer to the AppleEvent record * theKey = the keyword identifying this parameter, or 0 if theEvent is * actually a simple descriptor containing the parameter * theData = a pointer to a handle to store our result * Returns: an OSErr describing what went wrong * */ OSErr AEExtractTypeList(AppleEvent *theEvent, AEKeyword theKey, DescType ***theData) { long theCount, theIndex, actualSize; DescType returnedType, theType; OSErr theErr = noErr; AEDesc theList; if (theKey) theErr = AEGetParamDesc(theEvent, theKey, typeAEList, &theList); else { if (theEvent->descriptorType != typeAEList) theErr = AECoerceDesc(theEvent, typeAEList, &theList); else theErr = AEDuplicateDesc(theEvent, &theList); } if (theErr == noErr) { theErr = AECountItems(&theList, &theCount); if (theErr == noErr) { *theData = (DescType **)NewHandle(theCount * sizeof(DescType)); if (*theData) { for (theIndex = 1; theIndex <= theCount; theIndex++) { theErr = AEGetNthPtr(&theList, theIndex, typeType, &theKey, &returnedType, (void *)&theType, sizeof(typeType), &actualSize); if (theErr == noErr) (**theData)[theIndex - 1] = theType; else { theErr = errAEBadListItem; break; } } } else theErr = memFullErr; } else theErr = errAEWrongDataType; AEDisposeDesc(&theList); } return theErr; } /* * AEExtractPString(theEvent, theKey, theString) * * Purpose: Extracts a parameter of typeChar from the given event * Inputs: theEvent = a pointer to the AppleEvent record * theKey = the keyword identifying this parameter, or 0 if theEvent is * actually a simple descriptor containing the parameter * theString = pointer to a destination location to store the result * Returns: an OSErr describing what went wrong * */ OSErr AEExtractPString(AppleEvent *theEvent, AEKeyword theKey, uchar *theString) { long actualSize, theSize = 255; OSErr theErr = noErr; DescType actualType; AEDesc coercedDesc; if (theKey) { theErr = AEGetParamPtr(theEvent, theKey, typeChar, &actualType, (void *)&theString[1], theSize, &actualSize); if (theSize > actualSize) theSize = actualSize; } else { if (theEvent->descriptorType == typeChar) AEDuplicateDesc(theEvent, &coercedDesc); else theErr = AECoerceDesc(theEvent, typeChar, &coercedDesc); if (theErr == noErr) { actualSize = GetHandleSize(coercedDesc.dataHandle); BlockMove(*coercedDesc.dataHandle, &theString[1], *(uchar *)*coercedDesc.dataHandle); if (theSize > actualSize) theSize = actualSize; AEDisposeDesc(&coercedDesc); } } theString[0] = theSize; return theErr; } /* * AECoerceIntlToChar(theEvent, theKey, theSpec, count) * * Purpose: Coercion handler for making typeChars out of typeIntlTexts * Inputs: fromType = the original type of data (typeIntlText) * theData = pointer to the data * theSize = size of the pointed-to data * toType = the new type (typeChar) * refCon = a reference constant * result = a descriptor record containing the result * Returns: an OSErr describing what went wrong * */ pascal OSErr AECoerceIntlToChar(DescType fromType, Ptr theData, Size theSize, DescType toType, long refCon, AEDesc *result) { #if applec #pragma unused(fromType, toType, refCon) #endif return AECreateDesc(typeChar, (void *)(theData + 4), theSize - 4, result); } pascal OSErr AECoerceRectToList(DescType fromType, Ptr theData, Size theSize, DescType toType, long refCon, AEDesc *result) { #if applec #pragma unused(fromType, theSize, toType, refCon) #endif short *theItem = (short *)theData, i; OSErr theErr; theErr = AECreateList(nil, 0, false, result); if (theErr == noErr) { for (i = 0; i < 4; i++) if (theErr == noErr) theErr = AEPutPtr(result, 0, typeShortInteger, (Ptr)(theItem++), sizeof(short)); if (theErr != noErr) AEDisposeDesc(result); } return theErr; } pascal OSErr AECoerceListToRect(AEDesc *theAEDesc, DescType toType, long refCon, AEDesc *result) { #if applec #pragma unused(toType, refCon) #endif Rect theRect; short *theItem = (short *)&theRect, i; OSErr theErr = noErr; AEKeyword theKey; DescType theType; Size actualSize; for (i = 1; i <= 4; i++) if (theErr == noErr) theErr = AEGetNthPtr(theAEDesc, i, typeShortInteger, &theKey, &theType, (Ptr)(theItem++), sizeof(short), &actualSize); if (theErr == noErr) return AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), result); else return theErr; } /* * AEIdleProc(theEvent, theKey, theSpec, count) * * Purpose: Catch-all idle procedure used during AppleEvent processing * Inputs: theEvent = a pointer to the event record * sleep = a pointer to a sleep parameter we can set * mouseRgn = a pointer to a RgnHandle we can use to track mouseMoved events * Returns: true if we want to abort processing; false otherwise * */ pascal Boolean AEIdleProc(EventRecord *theEvent, long *sleep, RgnHandle *mouseRgn) { #if applec #pragma unused(sleep, mouseRgn) #endif Boolean isDialogEvent = IsDialogEvent(theEvent); switch (theEvent->what) { case activateEvt: if (isDialogEvent) HandleActivateDialog(theEvent); else HandleActivateEvent(theEvent); break; case updateEvt: if (isDialogEvent) HandleUpdateDialog(theEvent); else HandleUpdateEvent(theEvent); break; case osEvt: HandleOSEvent(theEvent); break; case diskEvt: HandleDiskEvent(theEvent); break; } return false; } \ No newline at end of file diff --git a/Source/C/AppleMenu.c b/Source/C/AppleMenu.c new file mode 100644 index 0000000..d4488f0 --- /dev/null +++ b/Source/C/AppleMenu.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif static DialogPtr gAboutHelpDialog = nil; static void CloseAboutHelp(void); /* * HandleAppleChoice(theItem) * * Purpose: Accepts menu events from the Apple menu * Inputs: theItem = the menu item number * Returns: nothing * */ void HandleAppleChoice(short theItem) { short accNumber; Str255 accName; switch (theItem) { case appleAboutItem: SendCreateWindow(kAboutWindowID); break; case appleAboutHelpItem: SendCreateWindow(kAboutHelpDialogID); break; default: GetItem(gAppleMenu, theItem, accName); accNumber = OpenDeskAcc(accName); break; } } /* * OpenAbout() * * Purpose: Handles the display of the about box * Inputs: none * Returns: nothing * */ void OpenAbout(void) { DescType openScreen, openFull, openPalette, drawQuality; ImageHandle theImage; OSErr theErr = noErr; FSSpec theFile; for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if (IsAboutBox(theImage)) { ChangeActive((*theImage)->window); return; } GetOpenDefaults(&openScreen, &openFull, &openPalette, &drawQuality); gGetAbout = true; theFile.vRefNum = -LMGetSFSaveDisk(); theFile.parID = LMGetCurDirStore(); BlockMove(gString[strAboutJPEGView], theFile.name, *gString[strAboutJPEGView] + 1); StartSpinning(); theErr = DoOpenDocument(&theFile, true, openScreen, openFull, false, true, openPalette, drawQuality, false, false, false, false); StopSpinning(&qd.arrow); } void OpenAboutHelp(void) { if (gAboutHelpDialog) { if (!WindowVisible(gAboutHelpDialog)) FWShowWindow(gAboutHelpDialog); return; } if (!(gAboutHelpDialog = AllocateDialog())) return; PushPort(); MySetPort(nil); if (gAboutHelpDialog = FWGetNewDialog(rAboutHelpDialog, (Ptr)gAboutHelpDialog, (WindowPtr)-1)) { PlaceWindow(gAboutHelpDialog, &gThePrefs.aboutHelpBounds, CenterWindow(gAboutHelpDialog)); } else DeallocateDialog(gAboutHelpDialog); PopPort(); } void HandleAboutHelpEvent(short theItem) { switch (theItem) { case kDialogClose: CloseAboutHelp(); return; } } WindowPtr GetAboutHelpWindow(void) { return gAboutHelpDialog; } static void CloseAboutHelp(void) { PushPort(); MySetPort(nil); if (gAboutHelpDialog) { SaveWindowPosition(gAboutHelpDialog, &gThePrefs.aboutHelpBounds); FWCloseDialog(gAboutHelpDialog); DisposeHandle(((DialogPeek)gAboutHelpDialog)->items); DeallocateDialog(gAboutHelpDialog); } gAboutHelpDialog = nil; PopPort(); ChangeActive(FWFrontWindow()); } \ No newline at end of file diff --git a/Source/C/BMP.c b/Source/C/BMP.c new file mode 100644 index 0000000..91483a2 --- /dev/null +++ b/Source/C/BMP.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "BMP.h" //===================================================================================== // BMPPrivates: private data structure for BMP images, maintained for each image. //===================================================================================== typedef struct BMPPrivates BMPPrivates, *BMPPrivatesPtr, **BMPPrivatesHandle; typedef (*ExtractProcPtr)(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates); struct BMPPrivates { ushort compression; // compression method used ushort depth; // calculated depth of the image ulong height, width; // size of the image ulong dataStart; // offset of the start of data CTabHandle decompColors; // color table to be used in decompression ExtractProcPtr extract; // pointer to extract function }; //===================================================================================== // Constants specific to this module //===================================================================================== enum { compRGB = 0, compRLE8 = 1, compRLE4 = 2 }; enum { errAllDone = 1 }; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static CTabHandle ExtractColorTable(uchar *dataStart, ulong offset, short depth, short colors, ulong *newOffset); static OSErr SetUpCompression(BMPPrivatesHandle privates, ImageHandle theImage); static OSErr DecompressBMPImage(uchar *dataStart, BMPPrivatesHandle privates, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length); static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow); static OSErr ExtractUncompressed(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates); static OSErr ExtractUncompressedRGB(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates); static OSErr ExtractRLE4(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates); static OSErr ExtractRLE8(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates); //===================================================================================== // Boolean idBMP(uchar *theData, long theSize) //===================================================================================== // Examines the given data and attempts to identify it as a BMP image. //===================================================================================== extern Boolean idBMP(uchar *theData, long theSize, short refNum, FSSpec *theSpec) { #if applec #pragma unused(theSize, refNum, theSpec) #endif return (theSize > 2 && theData[0] == 'B' && theData[1] == 'M'); } //===================================================================================== // OSErr OpenBMP(ImageHandle theImage) //===================================================================================== // Initializes the image record for a BMP image; note that since we are a simple // baseline BMP reader, we only read the first set of tags. //===================================================================================== #define GetIntelLong(a, o) \ ((ulong)a[o] + \ (ulong)(a[(o) + 1] << 8) + \ (ulong)(a[(o) + 2] << 16) + \ (ulong)(a[(o) + 3] << 24)) #define GetIntelShort(a, o) \ ((ushort)a[o] + \ (ushort)(a[(o) + 1] << 8)) extern OSErr OpenBMP(ImageHandle theImage) { long theLen = GetHandleSize((*theImage)->data); char hState = HGetState((*theImage)->data); BMPPrivatesHandle privates; ulong offset, headerSize; OSErr theErr = noErr; uchar *dataStart; if (!(privates = (BMPPrivatesHandle)NewHandleClear(sizeof(BMPPrivates)))) return memFullErr; (*theImage)->privateData = (Handle)privates; HLock((*theImage)->data); dataStart = (uchar *)*(*theImage)->data; (*privates)->dataStart = GetIntelLong(dataStart, 10); offset = 14; headerSize = GetIntelLong(dataStart, offset); if (headerSize <= 12) { // BITMAPCOREHEADER (*privates)->width = (*theImage)->grect.right = GetIntelShort(dataStart, offset + 4); (*privates)->height = (*theImage)->grect.bottom = GetIntelShort(dataStart, offset + 6); if (GetIntelShort(dataStart, offset + 8) != 1) theErr = codecBadDataErr; (*privates)->depth = (*theImage)->depth = GetIntelShort(dataStart, offset + 10); (*privates)->decompColors = ExtractColorTable(dataStart, offset + headerSize, (*privates)->depth, -1, &offset); } else { // BITMAPINFOHEADER (*privates)->width = (*theImage)->grect.right = GetIntelLong(dataStart, offset + 4); (*privates)->height = (*theImage)->grect.bottom = GetIntelLong(dataStart, offset + 8); if (GetIntelShort(dataStart, offset + 12) != 1) theErr = codecBadDataErr; (*privates)->depth = (*theImage)->depth = GetIntelShort(dataStart, offset + 14); (*privates)->compression = GetIntelLong(dataStart, offset + 16); (*privates)->decompColors = ExtractColorTable(dataStart, offset + headerSize, (*privates)->depth, GetIntelLong(dataStart, offset + 32), &offset); } if ((*privates)->depth == 24) (*privates)->depth = 32; else if ((*privates)->depth < 24 && !(*privates)->decompColors) theErr = codecBadDataErr; if (theErr == noErr) theErr = SetUpCompression(privates, theImage); if ((*privates)->decompColors) (*theImage)->ipalette = NewPalette(256, (*privates)->decompColors, pmTolerant, 0); (*theImage)->qrect = (*theImage)->crect = (*theImage)->grect; HSetState((*theImage)->data, hState); return theErr; } //===================================================================================== // OSErr DrawBMP(Handle theHandle, JVDrawParamsHandle theParams) //===================================================================================== // Draws a BMP image into the specified GWorld, from the srcRect into the dstRect, // clipping as dstRgn specifies. //===================================================================================== extern OSErr DrawBMP(Handle theHandle, JVDrawParamsHandle theParams) { BMPPrivatesHandle privates = (BMPPrivatesHandle)(*theParams)->privateData; NestedProgress theProgress = (*theParams)->progress; char hState = HGetState(theHandle); OSErr theErr = noErr; GWorldPtr theGWorld; uchar *dataStart; if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon); HLockHi(theHandle); if (theErr == noErr) { dataStart = (uchar *)StripAddress(*theHandle); theGWorld = NewTempGWorld((*privates)->width, (*privates)->height, (*privates)->depth, (*privates)->decompColors); if (theGWorld) { theErr = DecompressBMPImage(dataStart, privates, GetGWorldPixMap(theGWorld), (ICMProgressProcRecordPtr)&theProgress, GetHandleSize(theHandle)); if ((*theParams)->progress.aborted) theErr = codecAbortErr; DisposeGWorld(theGWorld); } else gIntError = errNoDrawMemory, theErr = memFullErr; } HSetState(theHandle, hState); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon); return theErr; } //===================================================================================== // OSErr CloneBMP(ImageHandle origImage, ImageHandle newImage) //===================================================================================== // Called when an image is cloned, to give us a chance to duplicate any secondary // storage. //===================================================================================== extern OSErr CloneBMP(ImageHandle origImage, ImageHandle newImage) { BMPPrivatesHandle origPrivates = (BMPPrivatesHandle)(*origImage)->privateData; BMPPrivatesHandle newPrivates = (BMPPrivatesHandle)(*newImage)->privateData; CTabHandle theColors; OSErr theErr; if (origPrivates && newPrivates) { if (theColors = (*origPrivates)->decompColors) { theErr = HandToHand((Handle *)&theColors); (*newPrivates)->decompColors = theColors; } } return theErr; } //===================================================================================== // OSErr CloseBMP(ImageHandle theImage) //===================================================================================== // Called before the image is disposed, to get rid of any secondary storage we // allocated on open. //===================================================================================== extern OSErr CloseBMP(ImageHandle theImage) { BMPPrivatesHandle privates = (BMPPrivatesHandle)(*theImage)->privateData; if (privates) if ((*privates)->decompColors) DisposeHandle((Handle)(*privates)->decompColors); return noErr; } //===================================================================================== // CTabHandle ExtractColorTable(uchar *dataStart, ulong offset, short depth, // short colors, ulong *newOffset) //===================================================================================== // Extracts the included BMP color table from the data at the given offset. //===================================================================================== static CTabHandle ExtractColorTable(uchar *dataStart, ulong offset, short depth, short colors, ulong *newOffset) { ulong count = (colors <= 0) ? (1L << depth) : colors, size = (1L << depth), i; uchar *data = dataStart + offset; Boolean isRGB3 = (colors == -1); CTabHandle theColors; if (depth == 24 && colors <= 0) return nil; if (count > size || count > 256) { *newOffset = offset + count * ((isRGB3) ? 3 : 4); return nil; } theColors = (CTabHandle)NewHandleClear(sizeof(ColorTable) + (size - 1) * sizeof(ColorSpec)); if (theColors) { (*theColors)->ctSeed = GetCTSeed(); (*theColors)->ctFlags = 0x8000; (*theColors)->ctSize = size; for (i = 0; i < count; i++) { (*theColors)->ctTable[i].rgb.blue = ((ushort)*data << 8) + *data, data++; (*theColors)->ctTable[i].rgb.green = ((ushort)*data << 8) + *data, data++; (*theColors)->ctTable[i].rgb.red = ((ushort)*data << 8) + *data, data++; if (!isRGB3) data++; } } *newOffset = data - dataStart; return theColors; } //===================================================================================== // OSErr SetUpCompression(BMPPrivatesHandle privates, ImageHandle theImage) //===================================================================================== // Sets up the compression parameters for the BMP image. //===================================================================================== static OSErr SetUpCompression(BMPPrivatesHandle privates, ImageHandle theImage) { OSErr theErr = noErr; switch ((*privates)->compression) { case compRGB: (*theImage)->compression = 0; BlockMove(gString[strUncompressed], (*theImage)->compressionDesc, *gString[strUncompressed] + 1); (*privates)->extract = ((*privates)->depth < 24) ? (ExtractProcPtr)ExtractUncompressed : (ExtractProcPtr)ExtractUncompressedRGB; break; case compRLE8: (*theImage)->compression = kRLE8Compression; BlockMove(gString[strRLE8], (*theImage)->compressionDesc, *gString[strRLE8] + 1); (*privates)->extract = (ExtractProcPtr)ExtractRLE8; break; case compRLE4: (*theImage)->compression = kRLE4Compression; BlockMove(gString[strRLE4], (*theImage)->compressionDesc, *gString[strRLE4] + 1); (*privates)->extract = (ExtractProcPtr)ExtractRLE4; break; default: theErr = codecBadDataErr; break; } return theErr; } //===================================================================================== // OSErr DecompressBMPImage(uchar *dataStart, BMPPrivatesHandle privates, // PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length) //===================================================================================== // Oversees the decompression of a BMP image, handling banding, and calling the // appropriate function to perform the actual decompression. //===================================================================================== static OSErr DecompressBMPImage(uchar *dataStart, BMPPrivatesHandle privates, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length) { uchar *ptr, *rowStart, *dataEnd = dataStart + length; char pState = GetPixelsState(dstPixMap); RgnHandle dstRgn = qd.thePort->visRgn; ulong bandRow = 0, row; char mmuMode = true32b; OSErr theErr = noErr; LockPixels(dstPixMap); rowStart = (uchar *)GetPixBaseAddr(dstPixMap) + (Height(&(*dstPixMap)->bounds) - 1) * ((*dstPixMap)->rowBytes & 0x3fff); ptr = dataStart + (*privates)->dataStart; for (row = 0; row < (*privates)->height; row++) { if (ptr < dataStart || ptr > dataEnd) { theErr = codecBadDataErr; break; } SwapMMUMode(&mmuMode); theErr = (*privates)->extract(&ptr, rowStart, privates); SwapMMUMode(&mmuMode); rowStart -= ((*dstPixMap)->rowBytes & 0x3fff); if (!(row & 63) && prog->progressProc) theErr = (OSErr)CallICMProgressProc(prog->progressProc, codecProgressUpdatePercent, FixRatio(row, (*privates)->height), prog->progressRefCon); if (++bandRow == Height(&(*dstPixMap)->bounds)) { CopyPixMapToDestination(dstPixMap, (*privates)->height - row - 1); bandRow = 0; rowStart = (uchar *)GetPixBaseAddr(dstPixMap) + (Height(&(*dstPixMap)->bounds) - 1) * ((*dstPixMap)->rowBytes & 0x3fff); } if (theErr != noErr) break; } if (theErr == errAllDone) theErr = noErr; if (theErr == noErr && bandRow) CopyPixMapToDestination(dstPixMap, (*privates)->height - (row + Height(&(*dstPixMap)->bounds) - bandRow)); SetPixelsState(dstPixMap, pState); return theErr; } //===================================================================================== // void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) //===================================================================================== // Copies the band contained in srcPixMap to the destination, offset from the top by // startRow. //===================================================================================== static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) { Rect srcRect = (*srcPixMap)->bounds, dstRect = (*srcPixMap)->bounds; PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); char srcState = HGetState((Handle)srcPixMap); char dstState = HGetState((Handle)dstPixMap); OffsetRect(&dstRect, 0, startRow); HLock((Handle)srcPixMap); HLock((Handle)dstPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &srcRect, &dstRect, srcCopy + ditherCopy, qd.thePort->visRgn); HSetState((Handle)dstPixMap, dstState); HSetState((Handle)srcPixMap, srcState); } //===================================================================================== // OSErr ExtractUncompressed(uchar **srcData, uchar *dstData, // BMPPrivatesHandle privates) //===================================================================================== // Pulls out a row of uncompressed 4 or 8 bit data. //===================================================================================== static OSErr ExtractUncompressed(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates) { ulong bytes = ((*privates)->width * (*privates)->depth + 7) / 8L; ulong offset = (*privates)->dataStart & 3; uchar *src = *srcData; while (bytes--) *dstData++ = *src++; *srcData = (uchar *)(((long)src - offset + 3) & 0xfffffffc) + offset; return noErr; } //===================================================================================== // OSErr ExtractUncompressedRGB(uchar **srcData, uchar *dstData, // BMPPrivatesHandle privates) //===================================================================================== // Pulls out a row of uncompressed RGB data, skipping the alpha channel in the // destination. //===================================================================================== static OSErr ExtractUncompressedRGB(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates) { // ulong offset = (*privates)->dataStart & 3; ulong col = (*privates)->width; uchar *src = *srcData; while (col--) { dstData++, *dstData++ = src[2], *dstData++ = src[1], *dstData++ = src[0]; src += 3; } // *srcData = (uchar *)(((long)src - offset + 3) & 0xfffffffc) + offset; *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractRLE4(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates) //===================================================================================== // Pulls out a row of RLE-compressed 4-bit data. //===================================================================================== static OSErr ExtractRLE4(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates) { uchar *src = *srcData, val, pixel = 0, shift = 4, sshift, spixel; short count, col = (*privates)->width; while (col) { if (count = *src++) { val = *src++; if ((col -= count) < 0) return codecBadDataErr; while (count--) { pixel |= (val & 0xf) << shift; if (shift = 4 - shift) *dstData++ = pixel, pixel = 0; val = (val << 4) | (val >> 4); } } else { count = *src++; if (count > 2) { if ((col -= count) < 0) return codecBadDataErr; sshift = 4, spixel = *src++; while (count--) { pixel |= ((spixel >> sshift) & 0xf) << shift; if (count && (sshift = 4 - sshift)) spixel = *src++; if (shift = 4 - shift) *dstData++ = pixel, pixel = 0; } src = (uchar *)(((long)src + 1) & 0xfffffffe); } else if (count == 0) break; else if (count == 1) return errAllDone; else { count = *src++; if ((col -= count) < 0) return codecBadDataErr; dstData += count >> 1; if (count & 1) if (shift = 4 - shift) dstData++; src++; // we skip the vertical offset for now } } } if (!shift) *dstData = pixel; while (!src[0] && !src[1]) src += 2; *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractRLE8(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates) //===================================================================================== // Pulls out a row of RLE-compressed 8-bit data. //===================================================================================== static OSErr ExtractRLE8(uchar **srcData, uchar *dstData, BMPPrivatesHandle privates) { short count, col = (*privates)->width; uchar *src = *srcData, val; while (col) { if (count = *src++) { val = *src++; if ((col -= count) < 0) return codecBadDataErr; while (count--) *dstData++ = val; } else { count = *src++; if (count > 2) { if ((col -= count) < 0) return codecBadDataErr; while (count--) *dstData++ = *src++; src = (uchar *)(((long)src + 1) & 0xfffffffe); } else if (count == 0) break; else if (count == 1) return errAllDone; else { count = *src++; if ((col -= count) < 0) return codecBadDataErr; dstData += count; src++; // we skip the vertical offset for now } } } while (!src[0] && !src[1]) src += 2; *srcData = src; return noErr; } \ No newline at end of file diff --git a/Source/C/Bottlenecks.c b/Source/C/Bottlenecks.c new file mode 100644 index 0000000..1614713 --- /dev/null +++ b/Source/C/Bottlenecks.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "Bottlenecks.h" //===================================================================================== // FixedPort: Holds old StdBits procedure information for when we fix up a port's // StdBits function to fix the QuickTime 1.5 bug. //===================================================================================== typedef struct FixedPort { struct FixedPort *next; CGrafPtr port; CQDProcs *oldprocs; CQDProcs newprocs; QDBitsUPP oldbits; } FixedPort, *FixedPortPtr, **FixedPortHandle; //===================================================================================== // Global variables local to this module //===================================================================================== static JVDrawParamsHandle gDrawParamsRoot = nil; static FixedPortPtr gFixedPortRoot = nil; static CQDProcs gBottlenecks; static QDBitsUPP gJVFixedBitsProc; static DeviceLoopDrawingUPP gDeviceCopy; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr DitherTableInit(void); static JVDrawParamsHandle FindParams(CGrafPtr thePort); static pascal void JVFixedBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask); static pascal void JVBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask); static void DrawOnAndOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect, JVDrawParamsHandle theParams); static void DrawOnscreen(PixMap *src, Rect *srcRect, Rect *dstRect, JVDrawParamsHandle theParams); static void DrawOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect, JVDrawParamsHandle theParams); static pascal void DeviceCopy(short depth, short deviceFlags, GDHandle targetDevice, void *tempParams); static void CustomCopy(PixMap *src, Rect *srcRect, Rect *dstRect, Boolean dither, RgnHandle mask, short quality); static Boolean IsGrayDevice(GDHandle theGDevice); static void DrawVHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect, Boolean dither, RgnHandle mask); static void DrawHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect, Boolean dither, RgnHandle mask); static void ShowScaleDither(Boolean scaling, Boolean dither, Boolean state, JVDrawParamsHandle theParams); static void CopyFields(CGrafPtr src, CGrafPtr dst, Rect *srcRect, Rect *dstRect); static Boolean DiffPixPat(PixPatHandle pp1, PixPatHandle pp2); static pascal void JVTextProc(short count, Ptr textAddr, Point numer, Point denom); static pascal void JVLineProc(Point newPt); static pascal void JVRectProc(GrafVerb verb, Rect *r); static pascal void JVRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight); static pascal void JVOvalProc(GrafVerb verb, Rect *r); static pascal void JVArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle); static pascal void JVPolyProc(GrafVerb verb, PolyHandle poly); static pascal void JVRgnProc(GrafVerb verb, RgnHandle rgn); //===================================================================================== // OSErr DrawingInit(void) //===================================================================================== // Initializes the bottlenecks record and the dithering table. //===================================================================================== extern OSErr DrawingInit(void) { KeepSpinning(); SetStdCProcs(&gBottlenecks); gBottlenecks.textProc = NewQDTextProc((ProcPtr)JVTextProc); gBottlenecks.lineProc = NewQDLineProc((ProcPtr)JVLineProc); gBottlenecks.rectProc = NewQDRectProc((ProcPtr)JVRectProc); gBottlenecks.rRectProc = NewQDRRectProc((ProcPtr)JVRRectProc); gBottlenecks.ovalProc = NewQDOvalProc((ProcPtr)JVOvalProc); gBottlenecks.arcProc = NewQDArcProc((ProcPtr)JVArcProc); gBottlenecks.polyProc = NewQDPolyProc((ProcPtr)JVPolyProc); gBottlenecks.rgnProc = NewQDRgnProc((ProcPtr)JVRgnProc); gBottlenecks.bitsProc = NewQDBitsProc((ProcPtr)JVBitsProc); gJVFixedBitsProc = NewQDBitsProc((ProcPtr)JVFixedBitsProc); gDeviceCopy = NewDeviceLoopDrawingProc((ProcPtr)DeviceCopy); KeepSpinning(); return DitherTableInit(); } //===================================================================================== // OSErr DitherTableInit(void) //===================================================================================== // Initializes the dithering and scaling tables. //===================================================================================== static OSErr DitherTableInit(void) { Handle tempHandle; uchar *theTable; short *table; short i, j, k; KeepSpinning(); if (!(tempHandle = NewHandleClear((3 + 4 + 5 + 6 + 7 + 8) * 256))) FatalError(errNoMemory); HLockHi(tempHandle); theTable = gScaleTable = (uchar *)StripAddress(*tempHandle); for (i = 3; i <= 8; i++) for (j = 0; j < 256; j++) for (k = 0; k < i; k++) *theTable++ = j; KeepSpinning(); if (!(tempHandle = NewHandleClear(sizeof(short) * 512))) FatalError(errNoMemory); HLockHi(tempHandle); table = gErrTable = (short *)StripAddress(*tempHandle) + 256; for (i = j = 1; i < 0x08; i++, j++) table[i] = j, table[-i] = -j; for (i = 0x08; i < 0x18; i++, j += !(i & 1) ? 1 : 0) table[i] = j, table[-i] = -j; for (i = 0x18; i < 0x38; i++, j += !(i & 3) ? 1 : 0) table[i] = j, table[-i] = -j; for (i = 0x38; i < 0x78; i++, j += !(i & 7) ? 1 : 0) table[i] = j, table[-i] = -j; for ( ; i <= 0x100; i++) { if (i != 0x100) table[i] = j; table[-i] = -j; } KeepSpinning(); return noErr; } //===================================================================================== // JVDrawParamsHandle NewDrawParams(Rect *bounds, short quality, Boolean quantize, // NestedProgressPtr progress, Handle privateData) //===================================================================================== // Creates and begins initializing a JVDrawParamsHandle in preparation for drawing. //===================================================================================== extern JVDrawParamsHandle NewDrawParams(Rect *bounds, short quality, Boolean quantize, NestedProgressPtr progress, Handle privateData) { JVDrawParamsHandle theParams; if (theParams = (JVDrawParamsHandle)NewHandleClear(sizeof(JVDrawParams))) { (*theParams)->bounds = *bounds; (*theParams)->quality = quality; (*theParams)->quantize = quantize; if (progress) { (*theParams)->progress = *progress; (*theParams)->progress.prog.progressRefCon = (long)theParams; } (*theParams)->privateData = privateData; } return theParams; } //===================================================================================== // SetUpDrawPort(JVDrawParamsHandle theParams, short whichPort, CGrafPtr thePort, // Rect *srcRect, Rect *dstRect, Boolean dither) //===================================================================================== // Initialize one of the three drawing ports in the JVDrawParamsHandle. //===================================================================================== extern void SetUpDrawPort(JVDrawParamsHandle theParams, short whichPort, CGrafPtr thePort, Rect *srcRect, Rect *dstRect, Boolean dither) { JVPortParams port; port.port = thePort; port.outer = (*theParams)->bounds; MapRect(&port.outer, srcRect, dstRect); port.dither = dither; switch (whichPort) { case kOnscreenPort: (*theParams)->on = port; break; case kOffscreenPort1: (*theParams)->off = port; break; case kOffscreenPort2: (*theParams)->extra = port; break; } } //===================================================================================== // OSErr PreflightDrawing(JVDrawParamsHandle theParams) //===================================================================================== // Inserts theParams into the local linked list of current drawing environments, and // creates a new destination port with the bottleneck procedures installed. //===================================================================================== extern OSErr PreflightDrawing(JVDrawParamsHandle theParams) { Rect bounds = (*theParams)->bounds, dbounds = { 0, 0, 1, 32 }, outer; GWorldPtr theGWorld; RgnHandle tempRgn; Rect theRect; (*theParams)->next = gDrawParamsRoot; (*theParams)->progress.aborted = false; gDrawParamsRoot = theParams; dbounds.right = Width(&(*theParams)->bounds); if (theGWorld = MyNewGWorld(&dbounds, 32, nil, nil, false, false)) { (*GetGWorldPixMap(theGWorld))->rowBytes &= 0xc000; if (tempRgn = NewRgn()) { SetEmptyRgn(theGWorld->visRgn); if ((*theParams)->on.port) { CopyRgn((*theParams)->on.port->visRgn, tempRgn); InsetRgn(tempRgn, -1, -1); outer = (*theParams)->on.outer; MapRgn(tempRgn, &outer, &bounds); UnionRgn(tempRgn, theGWorld->visRgn, theGWorld->visRgn); } if ((*theParams)->off.port) { CopyRgn((*theParams)->off.port->visRgn, tempRgn); InsetRgn(tempRgn, -1, -1); outer = (*theParams)->off.outer; MapRgn(tempRgn, &outer, &bounds); UnionRgn(tempRgn, theGWorld->visRgn, theGWorld->visRgn); if ((*theParams)->extra.port) { CopyRgn((*theParams)->extra.port->visRgn, tempRgn); InsetRgn(tempRgn, -1, -1); outer = (*theParams)->extra.outer; MapRgn(tempRgn, &outer, &bounds); UnionRgn(tempRgn, theGWorld->visRgn, theGWorld->visRgn); } } theRect = (*theParams)->bounds; RectRgn(theGWorld->clipRgn, &theRect); if (!(*theParams)->off.port && !(*theParams)->on.port) CopyRgn(theGWorld->clipRgn, theGWorld->visRgn); DisposeRgn(tempRgn); theGWorld->grafProcs = &gBottlenecks; (*theParams)->dummy = theGWorld; return noErr; } DisposeGWorld(theGWorld); } return memFullErr; } //===================================================================================== // OSErr PostflightDrawing(JVDrawParamsHandle theParams) //===================================================================================== // Removes theParams from the local linked list of current drawing environments, // disposing of the temporary destination port. //===================================================================================== extern OSErr PostflightDrawing(JVDrawParamsHandle theParams) { JVDrawParamsHandle params; OSErr theErr = noErr; if ((*theParams)->progress.aborted) theErr = codecAbortErr; if ((*theParams)->dummy) DisposeGWorld((*theParams)->dummy); if (theParams == gDrawParamsRoot) gDrawParamsRoot = (*theParams)->next; else for (params = gDrawParamsRoot; params; params = (*params)->next) if ((*params)->next == theParams) { (*params)->next = (*theParams)->next; break; } return theErr; } //===================================================================================== // JVDrawParamsHandle FindParams(CGrafPtr thePort) //===================================================================================== // Locates the parameter set associated with the given port. //===================================================================================== static JVDrawParamsHandle FindParams(CGrafPtr thePort) { JVDrawParamsHandle theParams; for (theParams = gDrawParamsRoot; theParams; theParams = (*theParams)->next) if ((*theParams)->dummy == thePort) return theParams; return nil; } //===================================================================================== // OSErr FixBits(CGrafPtr, Boolean on) //===================================================================================== // Turns on/off the QuickTime 1.5 image bug fix for a given port. //===================================================================================== extern OSErr FixBits(CGrafPtr thePort, Boolean on) { FixedPortPtr theFixedPort; if (gQTVersion != 0x0150) return noErr; if (on) { if (theFixedPort = (FixedPortPtr)NewPtrClear(sizeof(FixedPort))) { theFixedPort->next = gFixedPortRoot; gFixedPortRoot = theFixedPort; theFixedPort->port = thePort; if (theFixedPort->oldprocs = thePort->grafProcs) theFixedPort->newprocs = *thePort->grafProcs; else SetStdCProcs(&theFixedPort->newprocs); theFixedPort->oldbits = theFixedPort->newprocs.bitsProc; theFixedPort->newprocs.bitsProc = gJVFixedBitsProc; thePort->grafProcs = &theFixedPort->newprocs; } else return memFullErr; } else { for (theFixedPort = gFixedPortRoot; theFixedPort; theFixedPort = theFixedPort->next) if (theFixedPort->port == thePort) break; if (!theFixedPort) return paramErr; thePort->grafProcs = theFixedPort->oldprocs; if (theFixedPort == gFixedPortRoot) gFixedPortRoot = theFixedPort->next; else { for (theFixedPort = theFixedPort; theFixedPort->next; theFixedPort = theFixedPort->next) if (theFixedPort->next->port == thePort) break; if (theFixedPort) theFixedPort->next = theFixedPort->next->next; theFixedPort = theFixedPort->next; } DisposePtr((Ptr)theFixedPort); } return noErr; } //===================================================================================== // pascal void JVFixedBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, // RgnHandle mask) //===================================================================================== // Bottleneck routine to fix things under QuickTime 1.5 so that drawing cropped // images works correctly. Thanks for Mark Krueger for the bugfix! //===================================================================================== static pascal void JVFixedBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask) { long offsetH = srcRect->left, offsetV = srcRect->top, rb = src->rowBytes; Rect saveSrcBounds = src->bounds, tmpSrcRect = *srcRect; FixedPortPtr theFixedPort; Ptr saveBaseAddr = nil; for (theFixedPort = gFixedPortRoot; theFixedPort; theFixedPort = theFixedPort->next) if (theFixedPort->port == (CGrafPtr)qd.thePort) break; if (!theFixedPort) return; if (offsetH || offsetV) { if (rb & 0xc000) { rb &= 0x3fff; saveBaseAddr = src->baseAddr; if (src->pmVersion == 2) LockPixels(&src); if (src->pmVersion == 4) src->baseAddr += offsetV * rb + ((offsetH * src->pixelSize) >> 3); else if (src->pmVersion == 1) src->baseAddr = StripAddress(src->baseAddr) + offsetV * rb + ((offsetH * src->pixelSize) >> 3); OffsetRect(&tmpSrcRect, -offsetH, -offsetV); } else { BitMap *srcB = (BitMap *)src; saveBaseAddr = srcB->baseAddr; srcB->baseAddr += offsetH + (offsetV * rb); OffsetRect(&tmpSrcRect, -offsetH, -offsetV); } } src->bounds = tmpSrcRect; CallQDBitsProc(theFixedPort->oldbits, (BitMap *)src, &tmpSrcRect, dstRect, mode, mask); src->bounds = saveSrcBounds; if (saveBaseAddr) src->baseAddr = saveBaseAddr; } //===================================================================================== // pascal void JVBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, // RgnHandle mask) //===================================================================================== // Bottleneck routine for CopyBits. //===================================================================================== static pascal void JVBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask) { #if applec #pragma unused(mode, mask) #endif JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); PixMapHandle onPixMap = nil, offPixMap = nil; Boolean scaling = false; char offState; if (!theParams || (*theParams)->progress.aborted || ((*theParams)->progress.aborted = CheckAbort(theParams))) return; PushPort(); (*theParams)->src = src; (*theParams)->srcrect = *srcRect; (*theParams)->dstrect = *dstRect; if ((*theParams)->off.port) { offPixMap = GetGWorldPixMap((*theParams)->off.port); offState = GetPixelsState(offPixMap); LockPixels(offPixMap); scaling = !EqualSizeRect(&(*theParams)->bounds, &(*theParams)->off.outer); } if ((*theParams)->on.port) { onPixMap = GetGWorldPixMap((*theParams)->on.port); if (!scaling) scaling = !EqualSizeRect(&(*theParams)->bounds, &(*theParams)->on.outer); } if (Height(dstRect) > 8) ShowScaleDither(scaling, (*theParams)->on.dither, true, theParams); if ((*theParams)->quantize) FillHistogram(src); if ((*theParams)->on.port && (*theParams)->off.port) DrawOnAndOffscreen(src, srcRect, dstRect, theParams); else if ((*theParams)->on.port) DrawOnscreen(src, srcRect, dstRect, theParams); else if ((*theParams)->off.port) DrawOffscreen(src, srcRect, dstRect, theParams); if (Height(dstRect) > 8) ShowScaleDither(scaling, (*theParams)->on.dither, false, theParams); if ((*theParams)->off.port) SetPixelsState(offPixMap, offState); if (gSlideShow && !(*theParams)->progress.aborted) (*theParams)->progress.aborted = CheckAbort(theParams); PopPort(); } //===================================================================================== // void DrawOnAndOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect, // JVDrawParamsHandle theParams) //===================================================================================== // Do CopyBits drawing for both onscreen and offscreen. //===================================================================================== static void DrawOnAndOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect, JVDrawParamsHandle theParams) { PixMapHandle offPixMap = GetGWorldPixMap((*theParams)->off.port); Rect onDstRect = *dstRect, offDstRect = *dstRect; char hState = HGetState((Handle)offPixMap); RgnHandle tempRgn; PushPort(); MapRect(&onDstRect, &(*theParams)->bounds, &(*theParams)->on.outer); MapRect(&offDstRect, &(*theParams)->bounds, &(*theParams)->off.outer); MySetPort((*theParams)->off.port); (*theParams)->dstrect = offDstRect; CustomCopy(src, srcRect, &offDstRect, (*theParams)->off.dither, nil, (*theParams)->quality); if ((*theParams)->extra.port) { Rect extraDstRect = *dstRect; MapRect(&extraDstRect, &(*theParams)->bounds, &(*theParams)->extra.outer); MySetPort((*theParams)->extra.port); (*theParams)->dstrect = extraDstRect; CustomCopy(src, srcRect, &extraDstRect, (*theParams)->extra.dither, nil, (*theParams)->quality); } HLock((Handle)offPixMap); (*theParams)->src = *offPixMap; (*theParams)->srcrect = offDstRect; (*theParams)->dstrect = onDstRect; MySetPort((*theParams)->on.port); DeviceLoop((*theParams)->on.port->visRgn, gDeviceCopy, (long)theParams, singleDevices); if ((*theParams)->newupdates && (tempRgn = NewRgn())) { RectRgn(tempRgn, &onDstRect); DiffRgn((*theParams)->newupdates, tempRgn, (*theParams)->newupdates); DisposeRgn(tempRgn); } HSetState((Handle)offPixMap, hState); PopPort(); if (onDstRect.bottom >= (*theParams)->endprogress) (*theParams)->endprogress = 0; } //===================================================================================== // void DrawOnscreen(PixMap *src, Rect *srcRect, Rect *dstRect, // JVDrawParamsHandle theParams) //===================================================================================== // Do CopyBits drawing for onscreen. //===================================================================================== static void DrawOnscreen(PixMap *src, Rect *srcRect, Rect *dstRect, JVDrawParamsHandle theParams) { #if applec #pragma unused(src, srcRect) #endif Rect onDstRect = *dstRect; RgnHandle tempRgn; PushPort(); MapRect(&onDstRect, &(*theParams)->bounds, &(*theParams)->on.outer); (*theParams)->dstrect = onDstRect; MySetPort((*theParams)->on.port); DeviceLoop((*theParams)->on.port->visRgn, gDeviceCopy, (long)theParams, singleDevices); if ((*theParams)->newupdates && (tempRgn = NewRgn())) { RectRgn(tempRgn, &onDstRect); DiffRgn((*theParams)->newupdates, tempRgn, (*theParams)->newupdates); DisposeRgn(tempRgn); } PopPort(); if (onDstRect.bottom >= (*theParams)->endprogress) (*theParams)->endprogress = 0; } //===================================================================================== // void DrawOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect, // JVDrawParamsHandle theParams) //===================================================================================== // Do CopyBits drawing for offscreen. //===================================================================================== static void DrawOffscreen(PixMap *src, Rect *srcRect, Rect *dstRect, JVDrawParamsHandle theParams) { Rect offDstRect = *dstRect; PushPort(); MapRect(&offDstRect, &(*theParams)->bounds, &(*theParams)->off.outer); (*theParams)->dstrect = offDstRect; MySetPort((*theParams)->off.port); CustomCopy(src, srcRect, &offDstRect, (*theParams)->off.dither, nil, (*theParams)->quality); if ((*theParams)->extra.port) { Rect extraDstRect = *dstRect; MapRect(&extraDstRect, &(*theParams)->bounds, &(*theParams)->extra.outer); (*theParams)->dstrect = extraDstRect; MySetPort((*theParams)->extra.port); CustomCopy(src, srcRect, &extraDstRect, (*theParams)->extra.dither, nil, (*theParams)->quality); } PopPort(); } //===================================================================================== // pascal void DeviceCopy(short depth, short deviceFlags, GDHandle targetDevice, // void *tempParams) //===================================================================================== // Stub for calling CustomCopy for each device in the device list. //===================================================================================== static pascal void DeviceCopy(short depth, short deviceFlags, GDHandle targetDevice, void *tempParams) { #if applec #pragma unused(depth, deviceFlags) #endif JVDrawParamsHandle theParams = (JVDrawParamsHandle)tempParams; Rect srcRect = (*theParams)->srcrect, dstRect = (*theParams)->dstrect; GDHandle oldDevice = GetGDevice(); SetGDevice(targetDevice); CustomCopy((*theParams)->src, &srcRect, &dstRect, (*theParams)->on.dither, (*theParams)->on.port->visRgn, (*theParams)->quality); SetGDevice(oldDevice); } //===================================================================================== // Boolean IsGrayDevice(GDHandle theGDevice) //===================================================================================== // Checks an 8-bit device's color table and returns true if it's all grayscales. //===================================================================================== static Boolean IsGrayDevice(GDHandle theGDevice) { PixMapHandle thePixMap = (*theGDevice)->gdPMap; ColorSpec *theSpec; short i; if ((*thePixMap)->pmTable && (*(*thePixMap)->pmTable)->ctSize == 255) { theSpec = (*(*thePixMap)->pmTable)->ctTable; for (i = 0; i < 256; i++) { if (theSpec->rgb.red != theSpec->rgb.green || theSpec->rgb.red != theSpec->rgb.blue) return false; theSpec++; } return true; } return false; } //===================================================================================== // void CustomCopy(PixMap *src, Rect *srcRect, Rect *dstRect, Boolean dither, // RgnHandle mask, short quality) //===================================================================================== // Do our custom copying. //===================================================================================== static void CustomCopy(PixMap *src, Rect *srcRect, Rect *dstRect, Boolean dither, RgnHandle mask, short quality) { PixMapHandle dst = (*GetGDevice())->gdPMap; Boolean oldState; if ((*dst)->pixelType != RGBDirect) { ITabHandle theITab = (*GetGDevice())->gdITable; CTabHandle theCTab = (*dst)->pmTable; if (theCTab && ((*dst)->pixelSize == 8)) if (!theITab || ((*theITab)->iTabRes != 5) || ((*theITab)->iTabSeed != (*theCTab)->ctSeed)) MakeITable(nil, nil, 5); } ClipRect(dstRect); RGBForeColor(&gBlack); RGBBackColor(&gWhite); SpinIndef(); switch (quality) { case iqVHigh: DrawVHighQuality(src, dst, srcRect, dstRect, dither, mask); break; case iqHigh: DrawHighQuality(src, dst, srcRect, dstRect, dither, mask); break; case iqMedium: oldState = GetQDxDispatchPatchState(); if (oldState) RemoveQDxDispatchPatch(); CallProperBitsProc((BitMap *)src, srcRect, dstRect, dither ? srcCopy + ditherCopy : srcCopy, mask); if (oldState) InstallQDxDispatchPatch(true); break; } KeepSpinning(); return; } //===================================================================================== // void DrawVHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect, // Boolean dither, RgnHandle mask) //===================================================================================== // Do very high-quality custom drawing. //===================================================================================== static void DrawVHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect, Boolean dither, RgnHandle mask) { short srcDepth = (src->rowBytes & 0x8000) ? src->pixelSize : 1; if (srcDepth == 32 && (dither || (*dst)->pixelSize == 32)) { switch ((*dst)->pixelSize) { case 8: if (IsGrayDevice(GetGDevice())) break; case 16: case 32: DoCustomCopy(src, *dst, srcRect, dstRect, false, (*dst)->pixelSize); return; } } CallProperBitsProc((BitMap *)src, srcRect, dstRect, dither ? srcCopy + ditherCopy : srcCopy, mask); } //===================================================================================== // void DrawHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect, // Boolean dither, RgnHandle mask) //===================================================================================== // Do high-quality custom drawing. //===================================================================================== static void DrawHighQuality(PixMapPtr src, PixMapHandle dst, Rect *srcRect, Rect *dstRect, Boolean dither, RgnHandle mask) { short srcDepth = (src->rowBytes & 0x8000) ? src->pixelSize : 1; if ((srcDepth == 32) && (dither || (*dst)->pixelSize == 32)) { switch ((*dst)->pixelSize) { case 32: break; case 8: if (IsGrayDevice(GetGDevice())) break; case 16: DoCustomCopy(src, *dst, srcRect, dstRect, true, (*dst)->pixelSize); return; } } CallProperBitsProc((BitMap *)src, srcRect, dstRect, dither ? srcCopy + ditherCopy : srcCopy, mask); } //===================================================================================== // void ShowScaleDither(Boolean scaling, Boolean dither, Boolean state, // JVDrawParamsHandle theParams) //===================================================================================== // Do high-quality custom drawing. //===================================================================================== static void ShowScaleDither(Boolean scaling, Boolean dither, Boolean state, JVDrawParamsHandle theParams) { if ((*theParams)->progress.prog.progressProc) { if (scaling) CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressUpdateScaling, state, (*theParams)->progress.prog.progressRefCon); else if (dither) CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressUpdateDithering, state, (*theParams)->progress.prog.progressRefCon); } } //===================================================================================== // void CopyFields(CGrafPtr src, CGrafPtr dst, Rect *srcRect, Rect *dstRect) //===================================================================================== // Sets the drawing parameters of the dst port to be indentical to those in the src // port. //===================================================================================== static void CopyFields(CGrafPtr src, CGrafPtr dst, Rect *srcRect, Rect *dstRect) { Point thePoint; long x, y; MySetPort(dst); CopyRgn(src->clipRgn, dst->clipRgn); MapRgn(dst->clipRgn, srcRect, dstRect); thePoint = src->pnLoc; MapPt(&thePoint, srcRect, dstRect); MoveTo(thePoint.h, thePoint.v); x = (long)src->pnSize.h * (long)Width(dstRect) / (long)Width(srcRect); y = (long)src->pnSize.v * (long)Height(dstRect) / (long)Height(srcRect); PenSize(x ? x : 1, y ? y : 1); PenMode(src->pnMode); TextFont(src->txFont); TextFace(src->txFace); TextMode(src->txMode); x = (long)src->txSize * (long)Height(dstRect) / (long)Height(srcRect); TextSize(x ? x : 1); y = (long)src->spExtra * (long)Width(dstRect) / (long)Width(srcRect); SpaceExtra(y ? y : 1); if (src->portVersion & 0x8000) { PixPatHandle thePixPat; if (DiffPixPat(src->pnPixPat, dst->pnPixPat) && (thePixPat = NewPixPat())) { CopyPixPat(src->pnPixPat, thePixPat); PenPixPat(thePixPat); } if (DiffPixPat(src->bkPixPat, dst->bkPixPat) && (thePixPat = NewPixPat())) { CopyPixPat(src->bkPixPat, thePixPat); BackPixPat(thePixPat); } RGBForeColor(&src->rgbFgColor); RGBBackColor(&src->rgbBkColor); } else { PenPat(&((GrafPtr)src)->pnPat); BackPat(&((GrafPtr)src)->bkPat); ForeColor(src->fgColor); BackColor(src->bkColor); } } //===================================================================================== // Boolean DiffPixPat(PixPatHandle pp1, PixPatHandle pp2) //===================================================================================== // Compares two PixPatHandles; returns true if they're different. //===================================================================================== static Boolean DiffPixPat(PixPatHandle pp1, PixPatHandle pp2) { Size size1, size2; ulong *p1, *p2; if (!pp1) return false; if (!pp2) return true; if ((*pp1)->patType != (*pp2)->patType) return true; if (!(*pp1)->patData) return false; if (!(*pp2)->patData) return true; size1 = GetHandleSize((*pp1)->patData); size2 = GetHandleSize((*pp2)->patData); if (size1 != size2) return true; p1 = (ulong *)*(*pp1)->patData; p2 = (ulong *)*(*pp2)->patData; size1 >>= 2; while (size1--) if (*p1++ != *p2++) return true; return false; } //===================================================================================== // pascal void JVTextProc(short count, void *textAddr, Point numer, Point denom) //===================================================================================== // Bottleneck to handle text drawing. //===================================================================================== static pascal void JVTextProc(short count, Ptr textAddr, Point numer, Point denom) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect bounds, outer; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); CallProperTextProc(count, textAddr, numer, denom); PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); CallProperTextProc(count, textAddr, numer, denom); PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); CallProperTextProc(count, textAddr, numer, denom); PopPort(); } KeepSpinning(); } //===================================================================================== // pascal void JVLineProc(Point newPt) //===================================================================================== // Bottleneck to handle line drawing. //===================================================================================== static pascal void JVLineProc(Point newPt) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect bounds, outer; Point thePoint; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); thePoint = newPt; MapPt(&thePoint, &bounds, &outer); CallProperLineProc(thePoint); PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); thePoint = newPt; MapPt(&thePoint, &bounds, &outer); CallProperLineProc(thePoint); PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); thePoint = newPt; MapPt(&thePoint, &bounds, &outer); CallProperLineProc(thePoint); PopPort(); } KeepSpinning(); } //===================================================================================== // pascal void JVRectProc(GrafVerb verb, Rect *r) //===================================================================================== // Bottleneck to handle rectangle drawing. //===================================================================================== static pascal void JVRectProc(GrafVerb verb, Rect *r) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect theRect, bounds, outer; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperRectProc(verb, &theRect); PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperRectProc(verb, &theRect); PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperRectProc(verb, &theRect); PopPort(); } KeepSpinning(); } //===================================================================================== // pascal void JVRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight) //===================================================================================== // Bottleneck to handle rounded rectangle drawing. //===================================================================================== static pascal void JVRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect theRect, bounds, outer; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperRRectProc(verb, &theRect, ovalWidth, ovalHeight); PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperRRectProc(verb, &theRect, ovalWidth, ovalHeight); PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperRRectProc(verb, &theRect, ovalWidth, ovalHeight); PopPort(); } KeepSpinning(); } //===================================================================================== // pascal void JVOvalProc(GrafVerb verb, Rect *r) //===================================================================================== // Bottleneck to handle oval drawing. //===================================================================================== static pascal void JVOvalProc(GrafVerb verb, Rect *r) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect theRect, bounds, outer; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperOvalProc(verb, &theRect); PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperOvalProc(verb, &theRect); PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperOvalProc(verb, &theRect); PopPort(); } KeepSpinning(); } //===================================================================================== // pascal void JVArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle) //===================================================================================== // Bottleneck to handle arc drawing. //===================================================================================== static pascal void JVArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect theRect, bounds, outer; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperArcProc(verb, &theRect, startAngle, arcAngle); PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperArcProc(verb, &theRect, startAngle, arcAngle); PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); theRect = *r; MapRect(&theRect, &bounds, &outer); CallProperArcProc(verb, &theRect, startAngle, arcAngle); PopPort(); } KeepSpinning(); } //===================================================================================== // pascal void JVPolyProc(GrafVerb verb, PolyHandle poly) //===================================================================================== // Bottleneck to handle polygon drawing. //===================================================================================== static pascal void JVPolyProc(GrafVerb verb, PolyHandle poly) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect bounds, outer; PolyHandle thePoly; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); thePoly = poly; if (HandToHand((Handle *)&thePoly) == noErr) { MapPoly(thePoly, &bounds, &outer); CallProperPolyProc(verb, thePoly); DisposeHandle((Handle)thePoly); } PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); thePoly = poly; if (HandToHand((Handle *)&thePoly) == noErr) { MapPoly(thePoly, &bounds, &outer); CallProperPolyProc(verb, thePoly); DisposeHandle((Handle)thePoly); } PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); thePoly = poly; if (HandToHand((Handle *)&thePoly) == noErr) { MapPoly(thePoly, &bounds, &outer); CallProperPolyProc(verb, thePoly); DisposeHandle((Handle)thePoly); } PopPort(); } KeepSpinning(); } //===================================================================================== // pascal void JVRgnProc(GrafVerb verb, RgnHandle rgn) //===================================================================================== // Bottleneck to handle polygon drawing. //===================================================================================== static pascal void JVRgnProc(GrafVerb verb, RgnHandle rgn) { JVDrawParamsHandle theParams = FindParams((CGrafPtr)qd.thePort); Rect bounds, outer; RgnHandle theRgn; if (!theParams) return; bounds = (*theParams)->bounds; KeepSpinning(); if ((*theParams)->off.port) { PushPort(); outer = (*theParams)->off.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->off.port, &bounds, &outer); if (theRgn = NewRgn()) { CopyRgn(rgn, theRgn); MapRgn(theRgn, &bounds, &outer); CallProperRgnProc(verb, theRgn); DisposeHandle((Handle)theRgn); } PopPort(); if ((*theParams)->extra.port) { PushPort(); outer = (*theParams)->extra.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->extra.port, &bounds, &outer); if (theRgn = NewRgn()) { CopyRgn(rgn, theRgn); MapRgn(theRgn, &bounds, &outer); CallProperRgnProc(verb, theRgn); DisposeHandle((Handle)theRgn); } PopPort(); } } KeepSpinning(); if ((*theParams)->on.port) { PushPort(); outer = (*theParams)->on.outer; CopyFields((CGrafPtr)qd.thePort, (*theParams)->on.port, &bounds, &outer); if (theRgn = NewRgn()) { CopyRgn(rgn, theRgn); MapRgn(theRgn, &bounds, &outer); CallProperRgnProc(verb, theRgn); DisposeHandle((Handle)theRgn); } PopPort(); } KeepSpinning(); } //===================================================================================== // void CallProperBitsProc(BitMap *src, Rect *srcRect, Rect *dstRect, short mode, // RgnHandle mask) //===================================================================================== // Call StdBits, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperBitsProc(BitMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->bitsProc) CallQDBitsProc(((CGrafPtr)qd.thePort)->grafProcs->bitsProc, (BitMap *)src, srcRect, dstRect, mode, mask); else StdBits((BitMap *)src, srcRect, dstRect, mode, mask); } //===================================================================================== // void CallProperTextProc(short count, const void *textAddr, Point numer, Point denom) //===================================================================================== // Call StdText, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperTextProc(short count, Ptr textAddr, Point numer, Point denom) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->textProc) CallQDTextProc(((CGrafPtr)qd.thePort)->grafProcs->textProc, count, textAddr, numer, denom); else StdText(count, textAddr, numer, denom); } //===================================================================================== // void CallProperLineProc(Point newPt) //===================================================================================== // Call StdLine, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperLineProc(Point newPt) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->lineProc) CallQDLineProc(((CGrafPtr)qd.thePort)->grafProcs->lineProc, newPt); else StdLine(newPt); } //===================================================================================== // void CallProperRectProc(GrafVerb verb, Rect *r) //===================================================================================== // Call StdRect, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperRectProc(GrafVerb verb, Rect *r) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->rectProc) CallQDRectProc(((CGrafPtr)qd.thePort)->grafProcs->rectProc, verb, r); else StdRect(verb, r); } //===================================================================================== // void CallProperRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight) //===================================================================================== // Call StdRRect, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperRRectProc(GrafVerb verb, Rect *r, short ovalWidth, short ovalHeight) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->rRectProc) CallQDRRectProc(((CGrafPtr)qd.thePort)->grafProcs->rRectProc, verb, r, ovalWidth, ovalHeight); else StdRRect(verb, r, ovalWidth, ovalHeight); } //===================================================================================== // void CallProperOvalProc(GrafVerb verb, Rect *r) //===================================================================================== // Call StdOval, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperOvalProc(GrafVerb verb, Rect *r) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->ovalProc) CallQDOvalProc(((CGrafPtr)qd.thePort)->grafProcs->ovalProc, verb, r); else StdOval(verb, r); } //===================================================================================== // void CallProperArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle) //===================================================================================== // Call StdArc, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperArcProc(GrafVerb verb, Rect *r, short startAngle, short arcAngle) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->arcProc) CallQDArcProc(((CGrafPtr)qd.thePort)->grafProcs->arcProc, verb, r, startAngle, arcAngle); else StdArc(verb, r, startAngle, arcAngle); } //===================================================================================== // void CallProperPolyProc(GrafVerb verb, PolyHandle poly) //===================================================================================== // Call StdPoly, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperPolyProc(GrafVerb verb, PolyHandle poly) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->polyProc) CallQDPolyProc(((CGrafPtr)qd.thePort)->grafProcs->polyProc, verb, poly); else StdPoly(verb, poly); } //===================================================================================== // void CallProperRgnProc(GrafVerb verb, RgnHandle rgn) //===================================================================================== // Call StdRgn, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperRgnProc(GrafVerb verb, RgnHandle rgn) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->rgnProc) CallQDRgnProc(((CGrafPtr)qd.thePort)->grafProcs->rgnProc, verb, rgn); else StdRgn(verb, rgn); } //===================================================================================== // void CallProperPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, // RgnHandle mask, PixMap *matte, Rect *matteRect, short flags) //===================================================================================== // Call StdRgn, or a bottleneck function, as appropriate for the current port. //===================================================================================== extern void CallProperPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags) { if (qd.thePort->grafProcs && ((CGrafPtr)qd.thePort)->grafProcs->newProc1) CallStdPixProc((StdPixUPP)((CGrafPtr)qd.thePort)->grafProcs->newProc1, src, srcRect, matrix, mode, mask, matte, matteRect, flags); else StdPix(src, srcRect, matrix, mode, mask, matte, matteRect, flags); } \ No newline at end of file diff --git a/Source/C/ColorsMenu.c b/Source/C/ColorsMenu.c new file mode 100644 index 0000000..8464000 --- /dev/null +++ b/Source/C/ColorsMenu.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * HandleColorChoice(theItem) * * Purpose: Accepts menu events from the Color menu * Inputs: theItem = the menu item number * Returns: nothing * */ void HandleColorChoice(short theItem) { ImageHandle theImage = FrontImage(); short depth; if (!theImage) return; depth = (*(*theImage)->dmon)->depth; switch (theItem) { case colorSysItem: SendNewPalette(theImage, kAEPSystem); break; case colorGrayItem: SendNewPalette(theImage, kAEPGrayscale); break; case colorImageItem: SendNewPalette(theImage, kAEPImage); break; case colorQuantItem: if (depth <= 8) { Boolean spin = !(*theImage)->qpalette || ((*(*theImage)->qpalette)->pmEntries != (1 << depth)); if (spin) StartSpinning(); SendNewPalette(theImage, kAEPQuantized); if (spin) StopSpinning(&qd.arrow); } break; case colorDitherItem: SendDither(theImage, !Dithered(theImage)); break; } } /* * HandleQualityChoice(theItem) * * Purpose: Accepts menu events from the Quality submenu * Inputs: theItem = the menu item number * Returns: nothing * */ void HandleQualityChoice(short theItem) { ImageHandle theImage = FrontImage(); if (!theImage) return; switch (theItem) { case qualityVHighItem: SendQuality(theImage, kAEDQVeryHigh); break; case qualityHighItem: SendQuality(theImage, kAEDQHigh); break; case qualityMediumItem: SendQuality(theImage, kAEDQNormal); break; } } \ No newline at end of file diff --git a/Source/C/ColorsWindow.c b/Source/C/ColorsWindow.c new file mode 100644 index 0000000..82fc40a --- /dev/null +++ b/Source/C/ColorsWindow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local variables: * lColorsWindow = pointer to the colors window * */ static WindowPtr gColorsWindow = nil; /* * OpenColors() * * Purpose: Creates and initializes the colors window * Inputs: none * Returns: nothing * */ OSErr OpenColors(void) { Rect theRect, mainRect; OSErr theErr = noErr; Point where; if (gColorsWindow) { if (!WindowVisible(gColorsWindow)) FWShowWindow(gColorsWindow); return noErr; } if (!(gColorsWindow = AllocateWindow())) return memFullErr; PushPort(); MySetPort(nil); if (gColorsWindow = FWGetNewFloatingWindow(rColorsWindow, (Ptr)gColorsWindow, (WindowPtr)-1)) { MySetPort((CGrafPtr)gColorsWindow); theRect = gColorsWindow->portRect; OffsetRect(&theRect, -theRect.left, -theRect.top); if (gThePrefs.colorsBounds.top != gThePrefs.colorsBounds.bottom) { gThePrefs.colorsBounds.right = gThePrefs.colorsBounds.left + Width(&theRect); gThePrefs.colorsBounds.bottom = gThePrefs.colorsBounds.top + Height(&theRect); } GetActiveRect(gMainMonitor, &mainRect); where.h = mainRect.right - kWindowBorderWidth - Width(&theRect); where.v = mainRect.top + kWindowBorderHeight + GetMBarHeight() + gTitleBarHeight; PlaceWindow(gColorsWindow, &gThePrefs.colorsBounds, where); gThePrefs.colorsOpen = true; PopPort(); return noErr; } else theErr = memFullErr; CloseColors(); PopPort(); return theErr; } /* * CloseColors() * * Purpose: Closes the colors window * Inputs: none * Returns: nothing * */ void CloseColors(void) { PushPort(); MySetPort(nil); if (gColorsWindow) { gThePrefs.colorsOpen = false; SaveWindowPosition(gColorsWindow, &gThePrefs.colorsBounds); FWCloseWindow(gColorsWindow); DeallocateWindow(gColorsWindow); } gColorsWindow = nil; PopPort(); } /* * GetColorsWindow() * * Purpose: Returns a pointer to the statistics window * Inputs: none * Returns: nothing * */ WindowPtr GetColorsWindow(void) { return gColorsWindow; } /* * DrawColorsWindow() * * Purpose: Draws the statistics window * Inputs: none * Returns: nothing * */ void DrawColorsWindow(void) { short rows, cols, rowSize, colSize, theDepth, r, c; CTabHandle theColors; GDHandle theDevice; RGBColor theColor; Rect theRect; if (!gColorsWindow) return; PushPort(); MySetPort((CGrafPtr)gColorsWindow); theRect = gColorsWindow->portRect; GlobalRect(&theRect, gColorsWindow); theDevice = GetMaxDevice(&theRect); CalcVis((WindowPeek)gColorsWindow); if (theDevice) { theDepth = (*(*theDevice)->gdPMap)->pixelSize; theColors = (*(*theDevice)->gdPMap)->pmTable; if (theDepth <= 8) { switch (theDepth) { case 1: rows = 1, cols = 2; break; case 2: rows = 1, cols = 4; break; case 4: rows = 2, cols = 8; break; case 8: rows = 8, cols = 32; break; } rowSize = Height(&gColorsWindow->portRect) / rows - ((rows == 1) ? 1 : 0); colSize = Width(&gColorsWindow->portRect) / cols; for (r = 0; r < rows; r++) for (c = 0; c < cols; c++) { RGBForeColor(&(*theColors)->ctTable[r * cols + c].rgb); theRect.left = colSize * c + 1; theRect.right = theRect.left + colSize - 1; theRect.top = rowSize * r + 1; theRect.bottom = theRect.top + rowSize - 1; PaintRect(&theRect); } RGBForeColor(&gWhite); for (c = 0; c <= cols; c++) { MoveTo(c * colSize, gColorsWindow->portRect.top); LineTo(c * colSize, gColorsWindow->portRect.bottom); } for (r = 0; r <= rows; r++) { MoveTo(gColorsWindow->portRect.left, r * rowSize); LineTo(gColorsWindow->portRect.right, r * rowSize); } } else { colSize = Width(&gColorsWindow->portRect) / 256; rowSize = Height(&gColorsWindow->portRect) / 4; theRect.left = 1; theRect.right = 1 + colSize; for (c = 255; c > 0; c--) { theRect.top = 1; theRect.bottom = rowSize; theColor.red = theColor.green = theColor.blue = c << 8; RGBForeColor(&theColor); PaintRect(&theRect); theRect.top += rowSize; theRect.bottom += rowSize; theColor.green = theColor.blue = 0; RGBForeColor(&theColor); PaintRect(&theRect); theRect.top += rowSize; theRect.bottom += rowSize; theColor.green = theColor.red; theColor.red = 0; RGBForeColor(&theColor); PaintRect(&theRect); theRect.top += rowSize; theRect.bottom += rowSize; theColor.blue = theColor.green; theColor.green = 0; RGBForeColor(&theColor); PaintRect(&theRect); theRect.left += colSize; theRect.right += colSize; } } } PopPort(); } /* * DoColorsHelp(globalPt) * * Purpose: Pops up help for the colors windoid; needed because it should be displayed even * if it's not "active" * Inputs: globalPt = point, in global coordinates, where the mouse is * Returns: nothing * */ void DoColorsHelp(Point globalPt) { HMMessageRecord theRecord; Point tip = { 0, 0 }; Rect aRect; if (HMIsBalloon() || gInBackground) return; PushPort(); SetPort(gColorsWindow); if (HMExtractHelpMsg(kHMRectListResType, rColorsWindow, 1, kHMEnabledItem, &theRecord) == noErr) { tip = globalPt; aRect = gColorsWindow->portRect; GlobalRect(&aRect, gColorsWindow); HMShowBalloon(&theRecord, tip, &aRect, nil, 0, 0, kHMRegularWindow); } PopPort(); } \ No newline at end of file diff --git a/Source/C/CommentsWindow.c b/Source/C/CommentsWindow.c new file mode 100644 index 0000000..e5d136b --- /dev/null +++ b/Source/C/CommentsWindow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local variables: * gCommentsFontInfo = the font information for the comments window font (Geneva 9pt) * gCommentsWindow = pointer to the statistics window * gCommentsImage = handle of the image whose comments we're showing * gCommentsTextEdit = handle to the TextEdit record * gCommentsRect = the rect of the TextEdit record * */ static WindowPtr gCommentsWindow = nil; static FontInfo gCommentsFontInfo; static ImageHandle gCommentsImage = (ImageHandle)-1; static TEHandle gCommentsTextEdit = nil; static Rect gCommentsRect = { 0, 0, 10, 400 }; /* * OpenComments() * * Purpose: Creates and initializes the comments window * Inputs: none * Returns: nothing * */ OSErr OpenComments(void) { Rect theRect, mainRect; OSErr theErr = noErr; Point where; if (gCommentsWindow) { if (!WindowVisible(gCommentsWindow)) FWShowWindow(gCommentsWindow); return noErr; } if (!(gCommentsWindow = AllocateWindow())) return memFullErr; PushPort(); MySetPort(nil); if (gCommentsWindow = FWGetNewFloatingWindow(rCommentsWindow, (Ptr)gCommentsWindow, (WindowPtr)-1)) { MySetPort((CGrafPtr)gCommentsWindow); TextFont(geneva); TextSize(9); TextMode(srcCopy); TextFace(0); GetFontInfo(&gCommentsFontInfo); InsetRect(&gCommentsRect, 3, 0); gCommentsTextEdit = TENew(&gCommentsRect, &gCommentsRect); InsetRect(&gCommentsRect, -3, 0); if (gCommentsTextEdit) { (*gCommentsTextEdit)->txFont = geneva; (*gCommentsTextEdit)->txSize = 9; if (Width(&gThePrefs.commentsBounds) && Height(&gThePrefs.commentsBounds)) SizeWindow(gCommentsWindow, Width(&gThePrefs.commentsBounds), Height(&gThePrefs.commentsBounds), false); theRect = gCommentsWindow->portRect; OffsetRect(&theRect, -theRect.left, -theRect.top); if (gThePrefs.commentsBounds.top != gThePrefs.commentsBounds.bottom) { gThePrefs.commentsBounds.right = gThePrefs.commentsBounds.left + Width(&theRect); gThePrefs.commentsBounds.bottom = gThePrefs.commentsBounds.top + Height(&theRect); } GetActiveRect(gMainMonitor, &mainRect); where.h = mainRect.right - kWindowBorderWidth - theRect.right; where.v = mainRect.bottom - kWindowBorderHeight - theRect.bottom; PlaceWindow(gCommentsWindow, &gThePrefs.commentsBounds, where); DrawCommentsWindow(); gThePrefs.commentsOpen = true; PopPort(); return noErr; } else theErr = memFullErr; } else theErr = memFullErr; CloseComments(); PopPort(); return theErr; } /* * CloseComments() * * Purpose: Closes the comment window * Inputs: none * Returns: nothing * */ void CloseComments(void) { PushPort(); MySetPort(nil); if (gCommentsTextEdit) { TEDispose(gCommentsTextEdit); gCommentsTextEdit = nil; } if (gCommentsWindow) { gThePrefs.commentsOpen = false; SaveWindowPosition(gCommentsWindow, &gThePrefs.commentsBounds); FWCloseWindow(gCommentsWindow); DeallocateWindow(gCommentsWindow); } gCommentsWindow = nil; gCommentsImage = (ImageHandle)-1; PopPort(); } /* * NudgeComments(Rect *oldRect) * * Purpose: Nudges the comments window so it is fully visible on-screen * Inputs: none * Returns: nothing * */ void NudgeComments(Rect *oldRect) { Boolean top = false, left = false; MonitorHandle theMonitor; Rect theRect, monRect; if (gCommentsWindow) { theRect = gCommentsWindow->portRect; GlobalRect(&theRect, gCommentsWindow); GlobalRect(oldRect, gCommentsWindow); if (theMonitor = GetMostDevice(&theRect)) { GetActiveRect(theMonitor, &monRect); monRect.top += 11; // account for titlebar -- contact from Inf. Windoid code if ((oldRect->left - monRect.left) < (monRect.right - oldRect->right)) left = true; if ((oldRect->top - monRect.top) < (monRect.bottom - oldRect->bottom)) top = true; if (top) OffsetRect(&theRect, 0, monRect.top + kWindowBorderHeight - theRect.top); else OffsetRect(&theRect, 0, monRect.bottom - kWindowBorderHeight - theRect.bottom); if (left) OffsetRect(&theRect, monRect.left + kWindowBorderWidth - theRect.left, 0); else OffsetRect(&theRect, monRect.right - kWindowBorderWidth - theRect.right, 0); FWMoveWindow(gCommentsWindow, theRect.left, theRect.top, false); } } } /* * GetCommentsWindow() * * Purpose: Returns a pointer to the statistics window * Inputs: none * Returns: nothing * */ WindowPtr GetCommentsWindow(void) { return gCommentsWindow; } /* * DrawCommentsWindow() * * Purpose: Draws the statistics window * Inputs: none * Returns: nothing * */ void DrawCommentsWindow(void) { short width, maxwidth = 110, start, end, i; Boolean autoComments = (!gSlideShow && gThePrefs.autoComments) || (gSlideShow && (*gSlideOptions)->autoComments); Rect theRect, tempRect, oldRect; MonitorHandle theMonitor; ImageHandle theImage; WindowPtr theWindow; Boolean wasVisible; if (!gCommentsWindow) return; wasVisible = WindowVisible(gCommentsWindow); oldRect = gCommentsWindow->portRect; PushPort(); MySetPort((CGrafPtr)gCommentsWindow); for (theWindow = GetFirstWindow(); theWindow && !(theImage = FindImage(theWindow)); theWindow = NextWindow(theWindow)); if (autoComments && (!theImage || !(*theImage)->comments)) { if ((!gSlideShow && !gCommentsOpen) || gSlideShow) { PopPort(); CloseComments(); return; } } if (theImage != gCommentsImage) { FWHideWindow(gCommentsWindow); gCommentsImage = theImage; TESetSelect(0, 32767, gCommentsTextEdit); TEDelete(gCommentsTextEdit); TEScroll(0, (*gCommentsTextEdit)->viewRect.top - (*gCommentsTextEdit)->destRect.top, gCommentsTextEdit); if (theImage && (*theImage)->comments) { HLock((*theImage)->comments); TEInsert(*(*theImage)->comments, GetHandleSize((*theImage)->comments), gCommentsTextEdit); HUnlock((*theImage)->comments); (*gCommentsTextEdit)->viewRect.bottom = (*gCommentsTextEdit)->viewRect.top + (*gCommentsTextEdit)->lineHeight * (*gCommentsTextEdit)->nLines + gCommentsFontInfo.descent; tempRect = gCommentsWindow->portRect; GlobalRect(&tempRect, gCommentsWindow); theMonitor = GetMostDevice(&tempRect); GetActiveRect(theMonitor, &tempRect); tempRect.top += 11 + 2 * kWindowBorderHeight; if (Height(&(*gCommentsTextEdit)->viewRect) > Height(&tempRect)) (*gCommentsTextEdit)->viewRect.bottom = (*gCommentsTextEdit)->viewRect.top + Height(&tempRect); } else { (*gCommentsTextEdit)->viewRect.bottom = (*gCommentsTextEdit)->viewRect.top + (*gCommentsTextEdit)->lineHeight + gCommentsFontInfo.descent; TEInsert(&gString[strNoComments][1], *gString[strNoComments], gCommentsTextEdit); } theRect = (*gCommentsTextEdit)->viewRect; InsetRect(&theRect, -3, 0); for (i = 0; i < (*gCommentsTextEdit)->nLines; i++) { uchar *text; start = (*gCommentsTextEdit)->lineStarts[i]; end = (*gCommentsTextEdit)->lineStarts[i + 1] - 1; text = (uchar *)*(*gCommentsTextEdit)->hText + end; while (*text < 0x20) text--, end--; if (end > start) { HLock((Handle)(*gCommentsTextEdit)->hText); width = TextWidth(*(*gCommentsTextEdit)->hText, start, end - start + 1); HUnlock((Handle)(*gCommentsTextEdit)->hText); } if (width > maxwidth) maxwidth = width; } SizeWindow(gCommentsWindow, maxwidth + 6, Height(&theRect), true); if (autoComments) NudgeComments(&oldRect); if (wasVisible) { FWSelectWindow(gCommentsWindow); FWShowWindow(gCommentsWindow); } } PopPort(); } void UpdateCommentsWindow(void) { Rect theRect; if (!gCommentsWindow) return; PushPort(); MySetPort((CGrafPtr)gCommentsWindow); theRect = (*gCommentsTextEdit)->viewRect; TEUpdate(&theRect, gCommentsTextEdit); PopPort(); } extern void HandleCommentsClick(EventRecord *theEvent) { if (gDragMgrPresent && WaitMouseMoved(theEvent->where)) { RgnHandle theRgn = NewRgn(), tempRgn = NewRgn(); DragReference theDrag; Handle textHandle; Rect startRect; OSErr theErr; char hState; if (theRgn && tempRgn) { theErr = NewDrag(&theDrag); if (theErr == noErr) { textHandle = (Handle)TEGetText(gCommentsTextEdit); hState = HGetState(textHandle); HLock(textHandle); AddDragItemFlavor(theDrag, (ItemReference)gCommentsTextEdit, 'TEXT', *textHandle, GetHandleSize(textHandle), 0); HSetState(textHandle, hState); startRect = (*gCommentsTextEdit)->viewRect; SectRect(&startRect, &gCommentsWindow->portRect, &startRect); GlobalRect(&startRect, gCommentsWindow); RectRgn(theRgn, &startRect); RectRgn(tempRgn, &startRect); InsetRgn(tempRgn, 1, 1); DiffRgn(theRgn, tempRgn, theRgn); SetDragItemBounds(theDrag, (ItemReference)gCommentsTextEdit, &(*theRgn)->rgnBBox); SetCursor(&qd.arrow); theErr = TrackDrag(theDrag, theEvent, theRgn); DisposeDrag(theDrag); } } if (theRgn) DisposeRgn(theRgn); if (tempRgn) DisposeRgn(tempRgn); } else if (FrontWindow() != gCommentsWindow) SendMoveToFront(gCommentsWindow); } /* * DoCommentsHelp(globalPt) * * Purpose: Pops up help for the comments windoid; needed because it should be displayed even * if it's not "active" * Inputs: globalPt = point, in global coordinates, where the mouse is * Returns: nothing * */ void DoCommentsHelp(Point globalPt) { HMMessageRecord theRecord; Point tip = { 0, 0 }; Rect aRect; if (HMIsBalloon() || gInBackground) return; PushPort(); SetPort(gCommentsWindow); if (HMExtractHelpMsg(kHMRectListResType, rCommentsWindow, 1, kHMEnabledItem, &theRecord) == noErr) { tip = globalPt; aRect = gCommentsWindow->portRect; GlobalRect(&aRect, gCommentsWindow); HMShowBalloon(&theRecord, tip, &aRect, nil, 0, 0, kHMRegularWindow); } PopPort(); } \ No newline at end of file diff --git a/Source/C/CompressedResource.c b/Source/C/CompressedResource.c new file mode 100644 index 0000000..09428f2 --- /dev/null +++ b/Source/C/CompressedResource.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif static void compress_decompress(uchar *src_adr, ulong src_len, uchar *dst_adr, ulong *p_dst_len); static void fast_copy(uchar *p_src,uchar *p_dst,ulong len); Handle GetCompResource(OSType theType, short theID) { long srcLen, dstLen; Handle srcHandle; srcHandle = GetResource(theType, theID); if (!srcHandle) return nil; srcLen = GetHandleSize(srcHandle); SetHandleSize(srcHandle, 32768L); if (MemError()) { ReleaseResource(srcHandle); return nil; } HLock(srcHandle); BlockMove(*srcHandle, (uchar *)*srcHandle + 32768L - srcLen, srcLen); compress_decompress((uchar *)*srcHandle + 32768L - srcLen, srcLen, (uchar *)*srcHandle, (ulong *)&dstLen); SetHandleSize(srcHandle, dstLen); HUnlock(srcHandle); return srcHandle; } //------------------------------------------------------------------------------ #define UBYTE unsigned char /* Unsigned byte */ #define UWORD unsigned int /* Unsigned word (2 bytes) */ #define ULONG unsigned long /* Unsigned word (4 bytes) */ #define BOOL unsigned char /* Boolean */ #define REAL double /* USed for floating point stuff. */ #define DONE_PORT /* Don't do all this again. */ #define MALLOC_FAIL NULL /* Failure status from malloc() */ #define LOCAL static /* For non-exported routines. */ #define EXPORT /* Signals exported function. */ #define then /* Useful for aligning ifs. */ #define FLAG_BYTES 4 /* How many bytes does the flag use up? */ #define FLAG_COMPRESS 0 /* Signals that output was result of compression. */ #define FLAG_COPY 1 /* Signals that output was simply copied over. */ #define GROUP_CMP 34 #define GROUP_RAW 288 #define CONTROL_INIT 0xFFFF8000 void fast_copy(UBYTE *p_src,UBYTE *p_dst,ULONG len) /* Fast copy routine. */ {while (len--) *p_dst++=*p_src++;} static void compress_decompress(uchar *p_src_first, ulong src_len, uchar *p_dst_first, ulong *p_dst_len) /* Input : Specify input block using p_src_first and src_len. */ /* Input : Point p_dst_first to the start of the output zone. */ /* Input : Point p_dst_len to a ULONG to receive the output length. */ /* Input : Input block and output zone must not overlap. User knows */ /* Input : upperbound on output block length from earlier compression. */ /* Input : In any case, maximum expansion possible is nine times. */ /* Output : Length of output block written to *p_dst_len. */ /* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */ /* Output : Writes only in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */ { register UBYTE *p_src=p_src_first+FLAG_BYTES, *p_dst=p_dst_first; UBYTE *p_src_post=p_src_first+src_len; UBYTE *p_src_max16=p_src_first+src_len-(16*2); register ULONG control=1; if (*p_src_first==FLAG_COPY) {fast_copy(p_src_first+FLAG_BYTES,p_dst_first,src_len-FLAG_BYTES); *p_dst_len=src_len-FLAG_BYTES; return;} while (p_src!=p_src_post) {register UWORD unroll; if (control==1) {control=0x10000|*p_src++; control|=(*p_src++)<<8;} unroll= p_src<=p_src_max16 ? 16 : 1; while (unroll--) {if (control&1) {register UWORD lenmt; register UBYTE *p; lenmt=*p_src++; p=p_dst-(((lenmt&0xF0)<<4)|*p_src++); *p_dst++=*p++; *p_dst++=*p++; *p_dst++=*p++; lenmt&=0xF; while (lenmt--) *p_dst++=*p++;} else *p_dst++=*p_src++; control>>=1; } } *p_dst_len=p_dst-p_dst_first; } \ No newline at end of file diff --git a/Source/C/CopyFastScaledFrom32.c b/Source/C/CopyFastScaledFrom32.c new file mode 100644 index 0000000..079c692 --- /dev/null +++ b/Source/C/CopyFastScaledFrom32.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void CopyScaledFrom32(CopyDataPtr theData); #define kThreshold (1L << 9) #define AddHalfPixel(source) \ pixel = (source),\ blue += pixel & 0xff,\ pixel >>= 8,\ green += pixel & 0xff,\ pixel >>= 8,\ red += pixel & 0xff,\ divisor++ #define AddFullPixel(source) \ pixel = (source),\ blue += (pixel & 0xff) << 1,\ pixel >>= 8,\ green += (pixel & 0xff) << 1,\ pixel >>= 8,\ red += (pixel & 0xff) << 1,\ divisor += 2 DitherErrors evenDithering[kStackRowWidth + 2], // stack-based buffers for dithering; if these oddDithering[kStackRowWidth + 2]; // aren't enough, we allocate bigger ones ulong scaledRow[kStackRowWidth + 2]; // stack-based buffer for scaling { DitherErrorsPtr eBuffer, // pointers to whichever dithering oBuffer; // buffers we decide to use ulong *scaled, // pointer to the start of the scaling buffer *srcScaled, // temp. source pointer used during scaling *dstScaled; // destination pointer used during scaling Ptr src = theData->srcBase, // source pointer into original image data dst = theData->dstBase; // dest. pointer into real destination ulong srcPixelContributionY, // contribution in Y made by each source pixel srcPixelContributionX, // contribution in X made by each source pixel srcRemainingY = theData->yRemainder,// remaining Y contribution for source srcRemainingX; // remaining X contribution for current src ulong dstNeededY, // amount needed for complete dest. Y pixel dstNeededX, // amount needed for complete dest. X pixel red, green, blue, pixel, // temp. counter for rgb and holder for pixel divisor; // holder for the divisor uchar *table; // pointer to divisor table short *rgnPtr; // pointer to the region data long row = theData->height, // row counter col; // column counter Handle dynamicBuffer; // handle to any allocation we make RgnBuffer rgnData; // buffer for the region data // Allocate space for our buffers, if not enough room on stack // NOTE: This only works if the machine is in 32-bit addressing mode!!! if (theData->width > kStackRowWidth) { dynamicBuffer = AnyNewHandle((theData->width + 2) * (2 * sizeof(DitherErrors) + sizeof(ulong))); if (!dynamicBuffer) return; HLock(dynamicBuffer); eBuffer = (DitherErrorsPtr)*dynamicBuffer + 1; oBuffer = eBuffer + theData->width + 2; scaled = (ulong *)(oBuffer + theData->width + 1) + 1; } else { eBuffer = &evenDithering[1]; oBuffer = &oddDithering[1]; } scaled = &scaledRow[1]; // Clear out the dithering and scaling buffers if (theData->evodd & 1) ClearMem((Ptr)&eBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); else ClearMem((Ptr)&oBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); // Initialize the region data rgnData.zero = 0; rgnPtr = InitRegion(*theData->theRgn, &rgnData, &theData->boxRect); // Set up the source/destination quantities srcPixelContributionY = (theData->dstHeight << 10) / theData->srcHeight + 1; srcPixelContributionX = (theData->dstWidth << 10) / theData->srcWidth + 1; // The outermost (row) loop begins here; set up our pointers into the data while (row--) { srcScaled = (ulong *)src; dstScaled = (ulong *)scaled; // reset the columns counter and reset the source X remainder col = theData->width; srcRemainingX = theData->xRemainder; // The inner (column) loop begins here; set up our counters in the dest system while (col--) { dstNeededX = dstNeededY = 1L << 10; red = green = blue = divisor = 0; // Determine what sort of scaling is best for us if (dstNeededY < srcRemainingY && dstNeededX < srcRemainingX) { // no scaling needed for this particular destination pixel *dstScaled++ = *srcScaled; goto dontStore; } else if (dstNeededY < srcRemainingY) { // scaling needed in the X direction only if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled); srcScaled++; dstNeededX -= srcRemainingX; ScaleXLoop: if (dstNeededX > srcPixelContributionX) { AddFullPixel(*srcScaled++); dstNeededX -= srcPixelContributionX; goto ScaleXLoop; } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); srcRemainingX = srcPixelContributionX; } else if (dstNeededX < srcRemainingX) { // scaling needed in the Y direction only ulong origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled; if (srcRemainingY >= kThreshold) AddHalfPixel(*srcScaled); srcScaled = (ulong *)((uchar *)srcScaled + theData->srcRow); dstNeededY -= srcRemainingY; ScaleYLoop: if (dstNeededY > srcPixelContributionY) { AddFullPixel(*srcScaled); srcScaled = (ulong *)((uchar *)srcScaled + theData->srcRow); dstNeededY -= srcPixelContributionY; goto ScaleYLoop; } if (dstNeededY >= kThreshold) AddHalfPixel(*srcScaled); srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } else { // scaling needed in both directions ulong origSrcRemainingX = srcRemainingX; ulong origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled, *srcRowStart = srcScaled; if (srcRemainingY >= kThreshold) { if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled); srcScaled++; dstNeededX -= srcRemainingX; ScaleXYLoop1: if (dstNeededX > srcPixelContributionX) { AddFullPixel(*srcScaled++); dstNeededX -= srcPixelContributionX; goto ScaleXYLoop1; } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); srcRemainingX = origSrcRemainingX; dstNeededX = 1L << 10; } srcScaled = (ulong *)((uchar *)srcRowStart + theData->srcRow); dstNeededY -= srcRemainingY; ScaleXYLoop2: if (dstNeededY > srcPixelContributionY) { srcRowStart = srcScaled; if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled); srcScaled++; dstNeededX -= srcRemainingX; ScaleXYLoop3: if (dstNeededX > srcPixelContributionX) { AddFullPixel(*srcScaled++); dstNeededX -= srcPixelContributionX; goto ScaleXYLoop3; } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); srcScaled = (ulong *)((uchar *)srcRowStart + theData->srcRow); dstNeededY -= srcPixelContributionY; srcRemainingX = origSrcRemainingX; dstNeededX = 1L << 10; goto ScaleXYLoop2; } if (dstNeededY >= kThreshold) { if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled); srcScaled++; srcStart++; dstNeededX -= srcRemainingX; ScaleXYLoop4: if (dstNeededX > srcPixelContributionX) { AddFullPixel(*srcScaled++); srcStart++; dstNeededX -= srcPixelContributionX; goto ScaleXYLoop4; } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); } else { srcStart++; dstNeededX -= srcRemainingX; ScaleXYLoop5: if (dstNeededX > srcPixelContributionX) { srcStart++; dstNeededX -= srcPixelContributionX; goto ScaleXYLoop5; } } srcRemainingX = srcPixelContributionX; srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } switch (divisor) { case 0: *dstScaled++ = *srcScaled; break; case 1: pixel = red; pixel <<= 8; pixel += green; pixel <<= 8; pixel += blue; *dstScaled++ = pixel; break; case 2: pixel = red >> 1; pixel <<= 8; pixel += green >> 1; pixel <<= 8; pixel += blue >> 1; *dstScaled++ = pixel; break; case 3: case 4: case 5: case 6: case 7: table = (uchar *)(theData->sTable[divisor - 3]); pixel = table[red]; pixel <<= 8; pixel += table[green]; pixel <<= 8; pixel += table[blue]; *dstScaled++ = pixel; break; default: pixel = red / divisor; pixel <<= 8; pixel += green / divisor; pixel <<= 8; pixel += blue / divisor; *dstScaled++ = pixel; break; } // apply the final adjustment to the X counters dontStore: if (!(srcRemainingX -= dstNeededX)) { srcScaled++; srcRemainingX = srcPixelContributionX; } } // We now have a row; set up to do a dithered copy from it if ((++theData->evodd) & 1) theData->odd(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); else theData->even(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); if (!row) break; if (!--rgnData.yCount) rgnPtr = UpdateRegion(rgnPtr, &rgnData, &theData->boxRect); // apply final adjustments to the Y counters dstNeededY = 1L << 10; while (dstNeededY >= srcRemainingY) { src += theData->srcRow; dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } srcRemainingY -= dstNeededY; dst += theData->dstRow; } // Return space allocated for buffers if (theData->width > kStackRowWidth) DisposeHandle(dynamicBuffer); } \ No newline at end of file diff --git a/Source/C/CopyFastScaledFrom32.c copy b/Source/C/CopyFastScaledFrom32.c copy new file mode 100644 index 0000000..3d3284c --- /dev/null +++ b/Source/C/CopyFastScaledFrom32.c copy @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void CopyScaledFrom32(CopyDataPtr theData); #define kThreshold (1L << 9) #define AddHalfPixel(source) \ pixel = (source),\ blue += pixel & 0xff,\ pixel >>= 8,\ green += pixel & 0xff,\ pixel >>= 8,\ red += pixel & 0xff,\ divisor++ #define AddFullPixel(source) \ pixel = (source),\ blue += (pixel & 0xff) << 1,\ pixel >>= 8,\ green += (pixel & 0xff) << 1,\ pixel >>= 8,\ red += (pixel & 0xff) << 1,\ divisor += 2 DitherErrors evenDithering[1952], // stack-based buffers for dithering; if these oddDithering[1952]; // aren't enough, we allocate bigger ones DitherErrorsPtr eBuffer = &evenDithering[1],// pointers to whichever dithering oBuffer = &oddDithering[1]; // buffers we decide to use ulong scaledRow[1952]; // stack-based buffer for scaling ulong *scaled = &scaledRow[1], // pointer to the start of the scaling buffer *srcScaled, // temp. source pointer used during scaling *dstScaled; // destination pointer used during scaling Ptr src = theData->srcBase, // source pointer into original image data dst = theData->dstBase; // dest. pointer into real destination ulong srcPixelContributionY, // contribution in Y made by each source pixel srcPixelContributionX, // contribution in X made by each source pixel srcRemainingY = theData->yRemainder,// remaining Y contribution for source srcRemainingX; // remaining X contribution for current src ulong dstNeededY, // amount needed for complete dest. Y pixel dstNeededX, // amount needed for complete dest. X pixel red, green, blue, pixel, // temp. counter for rgb and holder for pixel divisor; // holder for the divisor uchar *table; // pointer to divisor table short *rgnPtr, // pointer to the region data row = theData->height, // row counter col; // column counter Handle dynamicBuffer; // handle to any allocation we make RgnBuffer rgnData; // buffer for the region data // Allocate space for our buffers, if not enough room on stack // NOTE: This only works if the machine is in 32-bit addressing mode!!! if (theData->width > 1950) { dynamicBuffer = AnyNewHandle((theData->width + 2) * (2 * sizeof(DitherErrors) + sizeof(ulong))); if (!dynamicBuffer) return; HLock(dynamicBuffer); eBuffer = (DitherErrorsPtr)*dynamicBuffer + 1; oBuffer = eBuffer + theData->width + 2; scaled = (ulong *)(oBuffer + theData->width + 1) + 1; } // Clear out the dithering and scaling buffers ClearMem((Ptr)&eBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); ClearMem((Ptr)&oBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); ClearMem((Ptr)&scaled[-1], (theData->width + 2) * sizeof(ulong)); // Initialize the region data rgnData.zero = 0; rgnPtr = InitRegion(*theData->theRgn, &rgnData, &theData->boxRect); // Set up the source/destination quantities srcPixelContributionY = (theData->dstHeight << 10) / theData->srcHeight + 1; srcPixelContributionX = (theData->dstWidth << 10) / theData->srcWidth + 1; // The outermost (row) loop begins here; set up our pointers into the data while (row--) { srcScaled = (ulong *)src; dstScaled = (ulong *)scaled; // reset the columns counter and reset the source X remainder col = theData->width; srcRemainingX = theData->xRemainder; // The inner (column) loop begins here; set up our counters in the dest system while (col--) { dstNeededX = dstNeededY = 1L << 10; red = green = blue = divisor = 0; // Determine what sort of scaling is best for us if (dstNeededY < srcRemainingY && dstNeededX < srcRemainingX) { // no scaling needed for this particular destination pixel *dstScaled++ = *srcScaled; goto dontStore; } else if (dstNeededY < srcRemainingY) { // scaling needed in the X direction only if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled++); dstNeededX -= srcRemainingX; while (dstNeededX > srcPixelContributionX) { dstNeededX -= srcPixelContributionX; AddFullPixel(*srcScaled++); } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); srcRemainingX = srcPixelContributionX; } else if (dstNeededX < srcRemainingX) { // scaling needed in the Y direction only ulong origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled; if (srcRemainingY >= kThreshold) AddHalfPixel(*srcScaled); srcScaled = (ulong *)((uchar *)srcScaled + theData->srcRow); dstNeededY -= srcRemainingY; while (dstNeededY > srcPixelContributionY) { dstNeededY -= srcPixelContributionY; AddFullPixel(*srcScaled); srcScaled = (ulong *)((uchar *)srcScaled + theData->srcRow); } if (dstNeededY >= kThreshold) AddHalfPixel(*srcScaled); srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } else { // scaling needed in both directions ulong origSrcRemainingX = srcRemainingX; ulong origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled, *srcRowStart = srcScaled; if (srcRemainingY >= kThreshold) { if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled++); dstNeededX -= srcRemainingX; while (dstNeededX > srcPixelContributionX) { dstNeededX -= srcPixelContributionX; AddFullPixel(*srcScaled++); } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); srcRemainingX = origSrcRemainingX; dstNeededX = 1L << 10; } srcScaled = (ulong *)((uchar *)srcRowStart + theData->srcRow); dstNeededY -= srcRemainingY; while (dstNeededY > srcPixelContributionY) { srcRowStart = srcScaled; if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled++); dstNeededX -= srcRemainingX; while (dstNeededX > srcPixelContributionX) { dstNeededX -= srcPixelContributionX; AddFullPixel(*srcScaled++); } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); srcScaled = (ulong *)((uchar *)srcRowStart + theData->srcRow); dstNeededY -= srcPixelContributionY; srcRemainingX = origSrcRemainingX; dstNeededX = 1L << 10; } if (dstNeededY >= kThreshold) { if (srcRemainingX >= kThreshold) AddHalfPixel(*srcScaled++); srcStart++; dstNeededX -= srcRemainingX; while (dstNeededX > srcPixelContributionX) { dstNeededX -= srcPixelContributionX; AddFullPixel(*srcScaled++); srcStart++; } if (dstNeededX >= kThreshold) AddHalfPixel(*srcScaled); } else { srcStart++; dstNeededX -= srcRemainingX; while (dstNeededX > srcPixelContributionX) { dstNeededX -= srcPixelContributionX; srcStart++; } } srcRemainingX = srcPixelContributionX; srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } switch (divisor) { case 0: *dstScaled++ = *srcScaled; break; case 1: pixel = red; pixel <<= 8; pixel += green; pixel <<= 8; pixel += blue; *dstScaled++ = pixel; break; case 2: pixel = red >> 1; pixel <<= 8; pixel += green >> 1; pixel <<= 8; pixel += blue >> 1; *dstScaled++ = pixel; break; case 3: case 4: case 5: case 6: case 7: table = (uchar *)(theData->sTable[divisor - 3]); pixel = table[red]; pixel <<= 8; pixel += table[green]; pixel <<= 8; pixel += table[blue]; *dstScaled++ = pixel; break; default: pixel = red / divisor; pixel <<= 8; pixel += green / divisor; pixel <<= 8; pixel += blue / divisor; *dstScaled++ = pixel; break; } // apply the final adjustment to the X counters dontStore: if (!(srcRemainingX -= dstNeededX)) { srcScaled++; srcRemainingX = srcPixelContributionX; } } // We now have a row; set up to do a dithered copy from it if ((++theData->evodd) & 1) theData->odd(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); else theData->even(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); if (!row) break; if (!--rgnData.yCount) rgnPtr = UpdateRegion(rgnPtr, &rgnData, &theData->boxRect); // apply final adjustments to the Y counters dstNeededY = 1L << 10; while (dstNeededY >= srcRemainingY) { src += theData->srcRow; dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } srcRemainingY -= dstNeededY; dst += theData->dstRow; } // Return space allocated for buffers if (theData->width > 1950) DisposeHandle(dynamicBuffer); \ No newline at end of file diff --git a/Source/C/CopyReallyFastScaledFrom32.c b/Source/C/CopyReallyFastScaledFrom32.c new file mode 100644 index 0000000..8f52902 --- /dev/null +++ b/Source/C/CopyReallyFastScaledFrom32.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void CopyScaledFrom32(CopyDataPtr theData); #define One (1L << 16) DitherErrorsPtr eBuffer, // pointers to whichever dithering oBuffer; // buffers we decide to use ulong *scaled, // pointer to the start of the scaling buffer *srcScaled, // temp. source pointer used during scaling *dstScaled; // destination pointer used during scaling Ptr src = theData->srcBase, // source pointer into original image data dst = theData->dstBase; // dest. pointer into real destination ulong srcPixelContributionY, // contribution in Y made by each source pixel srcPixelContributionX, // contribution in X made by each source pixel srcRemainingY = theData->yRemainder,// remaining Y contribution for source srcRemainingX; // remaining X contribution for current src ulong dstNeededY, // amount needed for complete dest. Y pixel dstNeededX; // amount needed for complete dest. X pixel short *rgnPtr; // pointer to the region data long row = theData->height, // row counter col; // column counter Handle dynamicBuffer; // handle to any allocation we make RgnBuffer rgnData; // buffer for the region data DitherErrors evenDithering[kStackRowWidth + 2], // stack-based buffers for dithering; if these oddDithering[kStackRowWidth + 2]; // aren't enough, we allocate bigger ones ulong scaledRow[kStackRowWidth + 2]; // stack-based buffer for scaling // Allocate space for our buffers, if not enough room on stack // NOTE: This only works if the machine is in 32-bit addressing mode!!! if (theData->width > kStackRowWidth) { dynamicBuffer = AnyNewHandle((theData->width + 2) * (2 * sizeof(DitherErrors) + sizeof(ulong))); if (!dynamicBuffer) return; HLock(dynamicBuffer); eBuffer = (DitherErrorsPtr)*dynamicBuffer + 1; oBuffer = eBuffer + theData->width + 2; scaled = (ulong *)(oBuffer + theData->width + 1) + 1; } else { eBuffer = &evenDithering[1]; oBuffer = &oddDithering[1]; } scaled = &scaledRow[1]; // Clear out the dithering and scaling buffers if (theData->evodd & 1) ClearMem((Ptr)&eBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); else ClearMem((Ptr)&oBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); // Initialize the region data rgnData.zero = 0; rgnPtr = InitRegion(*theData->theRgn, &rgnData, &theData->boxRect); // Set up the source/destination quantities srcPixelContributionY = (theData->dstHeight << 16) / theData->srcHeight + 1; srcPixelContributionX = (theData->dstWidth << 16) / theData->srcWidth + 1; // The outermost (row) loop begins here; set up our pointers into the data while (row--) { srcScaled = (ulong *)src; dstScaled = (ulong *)scaled; // reset the columns counter and reset the source X remainder col = theData->width; srcRemainingX = theData->xRemainder; // The inner (column) loops begin here; set up our counters in the dest system if (One >= srcRemainingY) { if ((One - srcRemainingY) < srcPixelContributionY) srcScaled += ((One - srcRemainingY) < srcRemainingY) ? 0 : (theData->srcRow >> 2); else srcScaled += (theData->srcRow >> 2); } while (col--) { dstNeededX = One; if (dstNeededX < srcRemainingX) *dstScaled++ = *srcScaled; else if ((dstNeededX -= srcRemainingX) < srcPixelContributionX) { if (dstNeededX < srcRemainingX) *dstScaled++ = *srcScaled++; else *dstScaled++ = *++srcScaled; srcRemainingX = srcPixelContributionX; } else { *dstScaled++ = *++srcScaled; srcScaled++; ScaleLoop1: if ((dstNeededX -= srcPixelContributionX) >= srcPixelContributionX) { srcScaled++; goto ScaleLoop1; } srcRemainingX = srcPixelContributionX; } // apply the final adjustment to the X counters srcRemainingX -= dstNeededX; } // We now have a row; set up to do a dithered copy from it if ((++theData->evodd) & 1) theData->odd(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); else theData->even(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); if (!row) break; if (!--rgnData.yCount) rgnPtr = UpdateRegion(rgnPtr, &rgnData, &theData->boxRect); // apply final adjustments to the Y counters dstNeededY = 1L << 16; while (dstNeededY >= srcRemainingY) { src += theData->srcRow; dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } srcRemainingY -= dstNeededY; dst += theData->dstRow; } // Return space allocated for buffers if (theData->width > kStackRowWidth) DisposeHandle(dynamicBuffer); \ No newline at end of file diff --git a/Source/C/CopyScaledFrom32.c b/Source/C/CopyScaledFrom32.c new file mode 100644 index 0000000..105f9a2 --- /dev/null +++ b/Source/C/CopyScaledFrom32.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void CopyScaledFrom32(CopyDataPtr theData); #define AddPixel(source, factor) \ pixel = (source),\ blue += factor * (pixel & 0xff),\ pixel >>= 8,\ green += factor * (pixel & 0xff),\ pixel >>= 8,\ red += factor * (pixel & 0xff) DitherErrorsPtr eBuffer, // pointers to whichever dithering oBuffer; // buffers we decide to use ulong *scaled, // pointer to the start of the scaling buffer *srcScaled, // temp. source pointer used during scaling *dstScaled; // destination pointer used during scaling Ptr src = theData->srcBase, // source pointer into original image data dst = theData->dstBase; // dest. pointer into real destination ulong srcPixelContributionY, // contribution in Y made by each source pixel srcPixelContributionX, // contribution in X made by each source pixel srcRemainingY = theData->yRemainder,// remaining Y contribution for source srcRemainingX; // remaining X contribution for current src ulong dstNeededY, // amount needed for complete dest. Y pixel dstNeededX, // amount needed for complete dest. X pixel red, green, blue, pixel; // temp. counter for rgb and holder for pixel short *rgnPtr; // pointer to the region data long row = theData->height, // row counter col; // column counter Handle dynamicBuffer; // handle to any allocation we make RgnBuffer rgnData; // buffer for the region data DitherErrors evenDithering[kStackRowWidth + 2], // stack-based buffers for dithering; if these oddDithering[kStackRowWidth + 2]; // aren't enough, we allocate bigger ones ulong scaledRow[kStackRowWidth + 2]; // stack-based buffer for scaling // Allocate space for our buffers, if not enough room on stack // NOTE: This only works if the machine is in 32-bit addressing mode!!! if (theData->width > kStackRowWidth) { dynamicBuffer = AnyNewHandle((theData->width + 2) * (2 * sizeof(DitherErrors) + sizeof(ulong))); if (!dynamicBuffer) return; HLock(dynamicBuffer); eBuffer = (DitherErrorsPtr)*dynamicBuffer + 1; oBuffer = eBuffer + theData->width + 2; scaled = (ulong *)(oBuffer + theData->width + 1) + 1; } else { eBuffer = &evenDithering[1]; oBuffer = &oddDithering[1]; } scaled = &scaledRow[1]; // Clear out the dithering and scaling buffers if (theData->evodd & 1) ClearMem((Ptr)&eBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); else ClearMem((Ptr)&oBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); // Initialize the region data rgnData.zero = 0; rgnPtr = InitRegion(*theData->theRgn, &rgnData, &theData->boxRect); // Set up the source/destination quantities srcPixelContributionY = (theData->dstHeight << 16) / theData->srcHeight + 1; srcPixelContributionX = (theData->dstWidth << 16) / theData->srcWidth + 1; // The outermost (row) loop begins here; set up our pointers into the data while (row--) { srcScaled = (ulong *)src; dstScaled = (ulong *)scaled; // reset the columns counter and reset the source X remainder col = theData->width; srcRemainingX = theData->xRemainder; // The inner (column) loop begins here; set up our counters in the dest system while (col--) { dstNeededX = dstNeededY = 1L << 16; red = green = blue = 0; // Determine what sort of scaling is best for us if (dstNeededY < srcRemainingY && dstNeededX < srcRemainingX) { // no scaling needed for this particular destination pixel *dstScaled++ = *srcScaled; goto dontStore; } else if (dstNeededY < srcRemainingY) { // scaling needed in the X direction only do { AddPixel(*srcScaled++, srcRemainingX); dstNeededX -= srcRemainingX; srcRemainingX = srcPixelContributionX; } while (dstNeededX > srcRemainingX); AddPixel(*srcScaled, dstNeededX); } else if (dstNeededX < srcRemainingX) { // scaling needed in the Y direction only ulong origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled; do { AddPixel(*srcScaled, srcRemainingY); srcScaled += (theData->srcRow >> 2); dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } while (dstNeededY > srcRemainingY); if (dstNeededY) AddPixel(*srcScaled, dstNeededY); srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } else { // scaling needed in both directions ulong multiplier, origSrcRemainingX = srcRemainingX; ulong origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled, *srcRowStart; do { srcRowStart = srcScaled; do { multiplier = (srcRemainingX * srcRemainingY) >> 16; AddPixel(*srcScaled++, multiplier); dstNeededX -= srcRemainingX; srcRemainingX = srcPixelContributionX; } while (dstNeededX > srcRemainingX); multiplier = (dstNeededX * srcRemainingY) >> 16; AddPixel(*srcScaled, multiplier); srcRemainingX = origSrcRemainingX; dstNeededX = 1L << 16; srcScaled = srcRowStart + (theData->srcRow >> 2); dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } while (dstNeededY > srcRemainingY); do { multiplier = (srcRemainingX * dstNeededY) >> 16; AddPixel(*srcScaled++, multiplier); srcStart++; dstNeededX -= srcRemainingX; srcRemainingX = srcPixelContributionX; } while (dstNeededX > srcRemainingX); multiplier = (dstNeededX * dstNeededY) >> 16; AddPixel(*srcScaled, multiplier); srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } pixel = red >> 16; pixel <<= 8; pixel += green >> 16; pixel <<= 8; pixel += blue >> 16; *dstScaled++ = pixel; // apply the final adjustment to the X counters dontStore: if (!(srcRemainingX -= dstNeededX)) { srcScaled++; srcRemainingX = srcPixelContributionX; } } // We now have a row; set up to do a dithered copy from it if ((++theData->evodd) & 1) theData->odd(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); else theData->even(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); if (!row) break; if (!--rgnData.yCount) rgnPtr = UpdateRegion(rgnPtr, &rgnData, &theData->boxRect); // apply final adjustments to the Y counters dstNeededY = 1L << 16; while (dstNeededY >= srcRemainingY) { src += theData->srcRow; dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } srcRemainingY -= dstNeededY; dst += theData->dstRow; } // Return space allocated for buffers if (theData->width > kStackRowWidth) DisposeHandle(dynamicBuffer); \ No newline at end of file diff --git a/Source/C/CopyScaledFrom32.c.float b/Source/C/CopyScaledFrom32.c.float new file mode 100644 index 0000000..da71db3 --- /dev/null +++ b/Source/C/CopyScaledFrom32.c.float @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void CopyScaledFrom32(CopyDataPtr theData); #define AddPixel(source, factor) \ pixel = (source),\ blue += factor * (pixel & 0xff),\ pixel >>= 8,\ green += factor * (pixel & 0xff),\ pixel >>= 8,\ red += factor * (pixel & 0xff) DitherErrors evenDithering[1952], // stack-based buffers for dithering; if these oddDithering[1952]; // aren't enough, we allocate bigger ones DitherErrorsPtr eBuffer = &evenDithering[1],// pointers to whichever dithering oBuffer = &oddDithering[1]; // buffers we decide to use ulong scaledRow[1952]; // stack-based buffer for scaling ulong *scaled = &scaledRow[1], // pointer to the start of the scaling buffer *srcScaled, // temp. source pointer used during scaling *dstScaled; // destination pointer used during scaling Ptr src = theData->srcBase, // source pointer into original image data dst = theData->dstBase; // dest. pointer into real destination float srcPixelContributionY, // contribution in Y made by each source pixel srcPixelContributionX, // contribution in X made by each source pixel srcRemainingY = (float)theData->yRemainder / 1024.0,// remaining Y contribution for source srcRemainingX; // remaining X contribution for current src float xRemainderFloat = (float)theData->xRemainder / 1024.0; float dstNeededY, // amount needed for complete dest. Y pixel dstNeededX; // amount needed for complete dest. X pixel float red, green, blue; ulong pixel; // temp. counter for rgb and holder for pixel short *rgnPtr, // pointer to the region data row = theData->height, // row counter col; // column counter Handle dynamicBuffer; // handle to any allocation we make RgnBuffer rgnData; // buffer for the region data // Allocate space for our buffers, if not enough room on stack // NOTE: This only works if the machine is in 32-bit addressing mode!!! if (theData->width > 1950) { dynamicBuffer = AnyNewHandle((theData->width + 2) * (2 * sizeof(DitherErrors) + sizeof(ulong))); if (!dynamicBuffer) return; HLock(dynamicBuffer); eBuffer = (DitherErrorsPtr)*dynamicBuffer + 1; oBuffer = eBuffer + theData->width + 2; scaled = (ulong *)(oBuffer + theData->width + 1) + 1; } // Clear out the dithering and scaling buffers ClearMem((Ptr)&eBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); ClearMem((Ptr)&oBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); ClearMem((Ptr)&scaled[-1], (theData->width + 2) * sizeof(ulong)); // Initialize the region data rgnData.zero = 0; rgnPtr = InitRegion(*theData->theRgn, &rgnData, &theData->boxRect); // Set up the source/destination quantities srcPixelContributionY = (float)theData->dstHeight / (float)theData->srcHeight; srcPixelContributionX = (float)theData->dstWidth / (float)theData->srcWidth; // The outermost (row) loop begins here; set up our pointers into the data while (row--) { srcScaled = (ulong *)src; dstScaled = (ulong *)scaled; // reset the columns counter and reset the source X remainder col = theData->width; srcRemainingX = xRemainderFloat; // The inner (column) loop begins here; set up our counters in the dest system while (col--) { dstNeededX = dstNeededY = 1.0; red = green = blue = 0.0; // Determine what sort of scaling is best for us if (dstNeededY < srcRemainingY && dstNeededX < srcRemainingX) { // no scaling needed for this particular destination pixel *dstScaled++ = *srcScaled; goto dontStore; } else if (dstNeededY < srcRemainingY) { // scaling needed in the X direction only do { red += ((uchar *)srcScaled)[1] * srcRemainingX; green += ((uchar *)srcScaled)[2] * srcRemainingX; blue += ((uchar *)srcScaled)[3] * srcRemainingX; srcScaled++; dstNeededX -= srcRemainingX; srcRemainingX = srcPixelContributionX; } while (dstNeededX > srcRemainingX); red += ((uchar *)srcScaled)[1] * dstNeededX; green += ((uchar *)srcScaled)[2] * dstNeededX; blue += ((uchar *)srcScaled)[3] * dstNeededX; dstNeededX -= srcRemainingX; srcRemainingX = srcPixelContributionX; } else if (dstNeededX < srcRemainingX) { // scaling needed in the Y direction only float origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled; do { red += ((uchar *)srcScaled)[1] * srcRemainingY; green += ((uchar *)srcScaled)[2] * srcRemainingY; blue += ((uchar *)srcScaled)[3] * srcRemainingY; srcScaled += (theData->srcRow >> 2); dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } while (dstNeededY > srcRemainingY); if (dstNeededY) { red += ((uchar *)srcScaled)[1] * dstNeededY; green += ((uchar *)srcScaled)[2] * dstNeededY; blue += ((uchar *)srcScaled)[3] * dstNeededY; } srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } else { // scaling needed in both directions float multiplier, origSrcRemainingX = srcRemainingX; float origSrcRemainingY = srcRemainingY; ulong *srcStart = srcScaled, *srcRowStart; do { srcRowStart = srcScaled; do { multiplier = srcRemainingX * srcRemainingY; red += ((uchar *)srcScaled)[1] * multiplier; green += ((uchar *)srcScaled)[2] * multiplier; blue += ((uchar *)srcScaled)[3] * multiplier; srcScaled++; dstNeededX -= srcRemainingX; srcRemainingX = srcPixelContributionX; } while (dstNeededX > srcRemainingX); multiplier = dstNeededX * srcRemainingY; red += ((uchar *)srcScaled)[1] * multiplier; green += ((uchar *)srcScaled)[2] * multiplier; blue += ((uchar *)srcScaled)[3] * multiplier; srcRemainingX = origSrcRemainingX; dstNeededX = 1.0; srcScaled = srcRowStart + (theData->srcRow >> 2); dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } while (dstNeededY > srcRemainingY); do { multiplier = srcRemainingX * dstNeededY; red += ((uchar *)srcScaled)[1] * multiplier; green += ((uchar *)srcScaled)[2] * multiplier; blue += ((uchar *)srcScaled)[3] * multiplier; srcScaled++; srcStart++; dstNeededX -= srcRemainingX; srcRemainingX = srcPixelContributionX; } while (dstNeededX > srcRemainingX); multiplier = dstNeededX * dstNeededY; red += ((uchar *)srcScaled)[1] * multiplier; green += ((uchar *)srcScaled)[2] * multiplier; blue += ((uchar *)srcScaled)[3] * multiplier; srcScaled = srcStart; srcRemainingY = origSrcRemainingY; } pixel = (uchar)red; pixel <<= 8; pixel |= (uchar)green; pixel <<= 8; pixel |= (uchar)blue; *dstScaled++ = pixel; // apply the final adjustment to the X counters dontStore: if (!(srcRemainingX -= dstNeededX)) { srcScaled++; srcRemainingX = srcPixelContributionX; } } // We now have a row; set up to do a dithered copy from it if ((++theData->evodd) & 1) theData->odd(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); else theData->even(scaled, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); if (!row) break; if (!--rgnData.yCount) rgnPtr = UpdateRegion(rgnPtr, &rgnData, &theData->boxRect); // apply final adjustments to the Y counters dstNeededY = 1.0; while (dstNeededY >= srcRemainingY) { src += theData->srcRow; dstNeededY -= srcRemainingY; srcRemainingY = srcPixelContributionY; } srcRemainingY -= dstNeededY; dst += theData->dstRow; } // Return space allocated for buffers if (theData->width > 1950) DisposeHandle(dynamicBuffer); \ No newline at end of file diff --git a/Source/C/CopyTo32.c b/Source/C/CopyTo32.c new file mode 100644 index 0000000..1e86201 --- /dev/null +++ b/Source/C/CopyTo32.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void CopyTo32(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, // DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, // short *rgnBuffer, uchar *errorMap, short columns) #if applec #pragma unused(iTable, cTable, eBuffer, oBuffer, errorMap) #endif ulong *src = srcRow; ulong *dst = (ulong *)dstRow; long rgnCol; if (!(rgnCol = *rgnBuffer++)) rgnCol -= *rgnBuffer++; while (columns--) { if (rgnCol > 0) { dst++, src++; if (!--rgnCol) rgnCol = rgnBuffer[-1] - rgnBuffer[0], rgnBuffer++; } else { *dst++ = *src++; if (!++rgnCol) rgnCol = rgnBuffer[0] - rgnBuffer[-1], rgnBuffer++; } } \ No newline at end of file diff --git a/Source/C/CopyUnscaledFrom32.c b/Source/C/CopyUnscaledFrom32.c new file mode 100644 index 0000000..b4b0684 --- /dev/null +++ b/Source/C/CopyUnscaledFrom32.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void CopyUnscaledFrom32(CopyDataPtr theData); DitherErrorsPtr eBuffer, oBuffer; Ptr src = theData->srcBase, dst = theData->dstBase; short *rgnPtr; long row = theData->height; Handle dynamicBuffer; RgnBuffer rgnData; DitherErrors evenDithering[kStackRowWidth + 2]; DitherErrors oddDithering[kStackRowWidth + 2]; // Allocate space for our buffers, if not enough room on stack // NOTE: This only works if the machine is in 32-bit addressing mode!!! if (theData->width > kStackRowWidth) { dynamicBuffer = AnyNewHandle((theData->width + 2) * 2 * sizeof(DitherErrors)); if (!dynamicBuffer) return; HLock(dynamicBuffer); eBuffer = (DitherErrorsPtr)*dynamicBuffer + 1; oBuffer = eBuffer + theData->width + 2; } else { eBuffer = &evenDithering[1]; oBuffer = &oddDithering[1]; } // Clear out the dithering buffers if (theData->evodd & 1) ClearMem((Ptr)&eBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); else ClearMem((Ptr)&oBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); // Initialize the region data rgnData.zero = 0; rgnPtr = InitRegion(*theData->theRgn, &rgnData, &theData->boxRect); // Beginning of outer (row) loop: determine even/odd and dither while (row--) { if ((++theData->evodd) & 1) theData->odd((ulong *)src, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); else theData->even((ulong *)src, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); if (!row) break; if (!--rgnData.yCount) rgnPtr = UpdateRegion(rgnPtr, &rgnData, &theData->boxRect); src += theData->srcRow; dst += theData->dstRow; } // Return space allocated for buffers if (theData->width > kStackRowWidth) DisposeHandle(dynamicBuffer); /* // Needed for all copy routines 0 ColorSpec *ctAddr; // color table address 4 uchar *itAddr; // inverse color table address 8 DitherErrorsPtr evenAddr,// even dithering buffer 12 oddAddr; // odd dithering buffer 16 DitherToDestPtr even, // address of even row dithering routine 20 odd; // address of odd row dithering routine 24 short *errTable; // address of dithering table 28 long srcRow, // row bytes in source pixmap 32 dstRow; // row bytes in destination pixmap 36 Ptr srcBase, // base address of source pixmap 40 dstBase; // base address of destination pixmap 44 long rgnBuffer[512], 2092 width, // total width of image 2096 height, // total height of image 2100 evodd; // word holding the even/odd row status 2104RgnHandle theRgn; // handle to the clipping region 2108Rect boxRect; // outer rect of the region // Needed only for CopyScaled routines long srcHeight, // height of the source rectangle srcWidth, // width of same dstHeight, // height of the destination rectangle dstWidth, // width of same xRemainder, // starting remainder in x yRemainder, // starting remainder in y columns, // internal counter for columns rows; // internal counter for rows Ptr outputAddr, // internal holder for destination address sTable[6]; // pointers into the scaling table } CopyData, *CopyDataPtr, **CopyDataHandle; DitherErrorsPtr eBuffer, oBuffer; Ptr src = theData->srcBase, dst = theData->dstBase; short *rgnPtr; long row = theData->height; Handle dynamicBuffer; RgnBuffer rgnData; DitherErrors evenDithering[1752], oddDithering[1752]; 00000000: 7C0802A6 mflr r0 00000004: BF01FFE0 stmw r24,-32(SP) 00000008: 90010008 stw r0,8(SP) 0000000C: 94215950 stwu SP,22864(SP) 00000010: 7C7F1B78 mr theData,r3 00000014: 807F082C lwz r3,2092(theData) ;theData->width 00000018: 83DF0024 lwz src,36(theData) ;theData->srcBase 0000001C: 2C0306D6 cmpwi r3,1750 00000020: 83BF0028 lwz dst,40(theData) ;theData->dstBase 00000024: 833F0830 lwz row,2096(theData) ;theData->height 00000028: 40810050 ble *+80 ; $00000078 if (theData->width > 1750) { dynamicBuffer = AnyNewHandle((theData->width + 2) * 2 * sizeof(DitherErrors)); if (!dynamicBuffer) return; HLock(dynamicBuffer); eBuffer = (DitherErrorsPtr)*dynamicBuffer + 1; oBuffer = eBuffer + theData->width + 2; 0000002C: 809F082C lwz r4,2092(theData) ;theData->width 00000030: 38840002 addi r4,r4,2 00000034: 5484083C slwi r4,r4,1 00000038: 1C64000C mulli r3,r4,12 0000003C: 48000001 bl .AnyNewHandle 00000040: 60000000 nop 00000044: 7C781B78 mr dynamicBuffer,r3 00000048: 2C180000 cmpwi dynamicBuffer,0 0000004C: 41820180 beq *+384 ; $000001CC 00000050: 7F03C378 mr r3,dynamicBuffer 00000054: 48000001 bl .HLock 00000058: 60000000 nop 0000005C: 80DF082C lwz r6,2092(theData) ;theData->width 00000060: 80B80000 lwz r5,0(dynamicBuffer) 00000064: 1CC6000C mulli r6,r6,12 00000068: 3B85000C addi eBuffer,r5,12 0000006C: 38C60018 addi r6,r6,24 00000070: 7F7C3214 add oBuffer,eBuffer,r6 00000074: 4280000C bc ALWAYS,cr0_LT,*+12 ; $00000080 } else { eBuffer = &evenDithering[1]; oBuffer = &oddDithering[1]; } 00000078: 3B81526C addi eBuffer,SP,21100 0000007C: 3B61004C addi oBuffer,SP,76 if (theData->evodd & 1) ClearMem((Ptr)&eBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); 00000080: 80FF0834 lwz r7,2100(theData) ;theData->evodd 00000084: 70E70001 andi. r7,r7,$0001 00000088: 41820020 beq *+32 ; $000000A8 0000008C: 811F082C lwz r8,2092(theData) ;theData->width 00000090: 387CFFF4 subi r3,eBuffer,12 00000094: 39080002 addi r8,r8,2 00000098: 1C88000C mulli r4,r8,12 0000009C: 48000001 bl .ClearMem 000000A0: 60000000 nop 000000A4: 4280001C bc ALWAYS,cr0_LT,*+28 ; $000000C0 else ClearMem((Ptr)&oBuffer[-1], (theData->width + 2) * sizeof(DitherErrors)); 000000A8: 813F082C lwz r9,2092(theData) ;theData->width 000000AC: 387BFFF4 subi r3,oBuffer,12 000000B0: 39290002 addi r9,r9,2 000000B4: 1C89000C mulli r4,r9,12 000000B8: 48000001 bl .ClearMem 000000BC: 60000000 nop 000000C0: 39400000 li r10,0 rgnData.zero = 0; rgnPtr = InitRegion(*theData->theRgn, &rgnData, &theData->boxRect); 000000C4: 9141A484 stw r10,-23420(SP) 000000C8: 817F0838 lwz r11,2104(theData) ;theData->theRgn 000000CC: 3881A480 subi r4,SP,23424 000000D0: 806B0000 lwz r3,0(r11) 000000D4: 38BF083C addi r5,theData,2108 ;theData->boxRect 000000D8: 48000001 bl .InitRegion 000000DC: 7C7A1B78 mr rgnPtr,r3 while (row--) { 000000E0: 428000C4 bc ALWAYS,cr0_LT,*+196 ; $000001A4 if ((++theData->evodd) & 1) theData->odd((ulong *)src, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); 000000E4: 819F0834 lwz r12,2100(theData) ;theData->evodd 000000E8: 398C0001 addi r12,r12,1 000000EC: 919F0834 stw r12,2100(theData) ;theData->evodd 000000F0: 718C0001 andi. r12,r12,$0001 000000F4: 4182003C beq *+60 ; $00000130 000000F8: 807F082C lwz r3,2092(theData) ;theData->width 000000FC: 7FA4EB78 mr r4,dst 00000100: 90610038 stw r3,56(SP) 00000104: 80BF0004 lwz r5,4(theData) ;theData->itAddr 00000108: 80DF0000 lwz r6,0(theData) ;theData->ctAddr 0000010C: 815F0018 lwz r10,24(theData) ;theData->errTable 00000110: 819F0014 lwz r12,20(theData) ;theData->odd 00000114: 7FC3F378 mr r3,src 00000118: 7F87E378 mr r7,eBuffer 0000011C: 7F68DB78 mr r8,oBuffer 00000120: 3921A488 subi r9,SP,23416 00000124: 48000001 bl .__ptr_glue 00000128: 60000000 nop 0000012C: 42800038 bc ALWAYS,cr0_LT,*+56 ; $00000164 else theData->even((ulong *)src, dst, theData->itAddr, theData->ctAddr, eBuffer, oBuffer, rgnData.buffer, theData->errTable, theData->width); 00000130: 809F082C lwz r4,2092(theData) ;theData->width 00000134: 7FC3F378 mr r3,src 00000138: 90810038 stw r4,56(SP) 0000013C: 80BF0004 lwz r5,4(theData) ;theData->itAddr 00000140: 80DF0000 lwz r6,0(theData) ;theData->ctAddr 00000144: 815F0018 lwz r10,24(theData) ;theData->errTable 00000148: 819F0010 lwz r12,16(theData) ;theData->even 0000014C: 7FA4EB78 mr r4,dst 00000150: 7F87E378 mr r7,eBuffer 00000154: 7F68DB78 mr r8,oBuffer 00000158: 3921A488 subi r9,SP,23416 0000015C: 48000001 bl .__ptr_glue 00000160: 60000000 nop if (!row) break; 00000164: 2C190000 cmpwi row,0 00000168: 4182004C beq *+76 ; $000001B4 if (!--rgnData.yCount) rgnPtr = UpdateRegion(rgnPtr, &rgnData, &theData->boxRect); 0000016C: 80A1A480 lwz r5,-23424(SP) 00000170: 38A5FFFF subi r5,r5,1 00000174: 2C050000 cmpwi r5,0 00000178: 90A1A480 stw r5,-23424(SP) 0000017C: 40820018 bne *+24 ; $00000194 00000180: 7F43D378 mr r3,rgnPtr 00000184: 3881A480 subi r4,SP,23424 00000188: 38BF083C addi r5,theData,2108 ;theData->boxRect 0000018C: 48000001 bl .UpdateRegion 00000190: 7C7A1B78 mr rgnPtr,r3 src += theData->srcRow; dst += theData->dstRow; 00000194: 80DF001C lwz r6,28(theData) ;theData->srcRow 00000198: 80FF0020 lwz r7,32(theData) ;theData->dstRow 0000019C: 7FDE3214 add src,src,r6 000001A0: 7FBD3A14 add dst,dst,r7 } 000001A4: 7F28CB78 mr r8,row 000001A8: 2C080000 cmpwi r8,0 000001AC: 3B39FFFF subi row,row,1 000001B0: 4082FF34 bne *-204 ; $000000E4 if (theData->width > 1750) DisposeHandle(dynamicBuffer); 000001B4: 813F082C lwz r9,2092(theData) ;theData->width 000001B8: 2C0906D6 cmpwi r9,1750 000001BC: 40810010 ble *+16 ; $000001CC 000001C0: 7F03C378 mr r3,dynamicBuffer 000001C4: 48000001 bl .DisposeHandle 000001C8: 60000000 nop 000001CC: 8001A6B8 lwz r0,-22856(SP) 000001D0: 3821A6B0 subi SP,SP,22864 000001D4: 7C0803A6 mtlr r0 000001D8: BB01FFE0 lmw r24,-32(SP) 000001DC: 4E800020 blr */ \ No newline at end of file diff --git a/Source/C/CoreEventHandlers.c b/Source/C/CoreEventHandlers.c new file mode 100644 index 0000000..affe8df --- /dev/null +++ b/Source/C/CoreEventHandlers.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * HandleClone(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the clone event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleClone(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif Boolean visible = false, foundVisible = false; WindowPtr newWindow, behindWindow; ObjectTokenHandle theToken; AEDesc theList, theObject; OSErr theErr = noErr; short i, count; AEBegin(); theErr = AEExtractBoolean(theEvent, keyVisible, &visible); if (theErr == noErr) foundVisible = true; theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if ((theObject.descriptorType == cWindow) || (theObject.descriptorType == cDocument)) { count = (*theToken)->count; theErr = AEExtractInsertionLoc(theEvent, keyAEInsertHere, &behindWindow); if (theErr != noErr) { behindWindow = (WindowPtr)(*theToken)->object[count - 1]; theErr = noErr; } if (count > 1) theErr = AECreateList(nil, 0, false, &theList); for (i = 0; i < count; i++) { if (theErr == noErr) { theErr = DoCloneWindow((WindowPtr)(*theToken)->object[i], behindWindow, &newWindow); if (theErr == noErr) { if (visible || (!foundVisible && WindowVisible((WindowPtr)(*theToken)->object[i]))) { FWShowWindow(newWindow); if (newWindow == FWFrontWindow()) ChangeActive(newWindow); } theErr = MakeWindowObject((WindowPtr)newWindow, &theObject); if (theErr == noErr) { if (count == 1) { if (reply->dataHandle) theErr = AEPutParamDesc(reply, keyAEResult, &theObject); } else theErr = AEPutDesc(&theList, i + 1, &theObject); } AEDisposeDesc(&theObject); } behindWindow = newWindow; } } if (count > 1) { if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList); AEDisposeDesc(&theList); } } else theErr = errAEEventNotHandled; AEDisposeDesc(&theObject); } AEEnd(); return theErr; } /* * HandleClose(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the close event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleClose(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(reply, refCon) #endif ObjectTokenHandle theToken; Boolean restoreColors; OSErr theErr = noErr; AEDesc theObject; short i, count; AEBegin(); theErr = AEExtractBoolean(theEvent, keyRestoreColors, &restoreColors); if (theErr != noErr) restoreColors = gThePrefs.restoreColors; theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if ((theObject.descriptorType == cWindow) || (theObject.descriptorType == cDocument)) { count = (*theToken)->count; for (i = count - 1; i >= 0; i--) { if (theErr == noErr) theErr = DoCloseWindow((WindowPtr)(*theToken)->object[i], restoreColors); } } else theErr = errAEEventNotHandled; AEDisposeDesc(&theObject); } AEEnd(); return theErr; } /* * HandleCountElements(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the count elements event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleCountElements(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif ObjectTokenHandle theToken; AEDesc theList, theObject; OSErr theErr = noErr; DescType theType; short i, count; long val; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theErr = AEExtractType(theEvent, keyAEObjectClass, &theType); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; count = (*theToken)->count; if (count > 1) theErr = AECreateList(nil, 0, false, &theList); for (i = 0; i < count; i++) { val = 0; switch (theObject.descriptorType) { case typeNull: if (theType == cWindow) val = CountWindows(); else if (theType == cDocument) val = CountDocuments(); break; case cWindow: if ((theType == cDocument) || (theType == cDrawingArea)) if (FindImage((WindowPtr)(*theToken)->object[i])) val = 1; break; case cDocument: if ((theType == cImage) || (theType == cFile)) val = 1; break; case cDrawingArea: if (theType == cImage) val = 1; break; case cImage: if (theType == cPixelMap) if ((*FindImage((WindowPtr)(*theToken)->object[i]))->gworld) val = 1; break; case cFile: if (theType == cImage) val = 1; break; case typeProperty: if (((*theToken)->objclass == cWindow) && ((*theToken)->property == pSelection)) val = 1; break; } if (reply->dataHandle) { if (count == 1) theErr = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (void *)&val, sizeof(long)); else theErr = AEPutPtr(&theList, i + 1, typeLongInteger, (void *)&val, sizeof(long)); } if (theErr != noErr) break; } if (count > 1) { if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList); AEDisposeDesc(&theList); } } else theErr = errAEEventNotHandled; AEDisposeDesc(&theObject); } AEEnd(); return theErr; } /* * HandleCreateElement(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the create element event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleCreateElement(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif DescType theClass, theType, actualType; WindowPtr behindWindow, theWindow; AEDesc theRecord, theObject; OSErr theErr = noErr; long actualSize; AEBegin(); theErr = AEExtractType(theEvent, keyAEObjectClass, &theClass); if (theErr == noErr) { if (theClass == cWindow) { theErr = AEExtractInsertionLoc(theEvent, keyAEInsertHere, &behindWindow); if (theErr == noErr) { theErr = AEGetParamDesc(theEvent, keyAEPropData, typeAERecord, &theRecord); if (theErr == noErr) { theErr = AEGetKeyPtr(&theRecord, pWindowType, typeEnumerated, &actualType, (void *)&theType, sizeof(DescType), &actualSize); if (theErr == noErr) theErr = DoCreateWindow(theType, behindWindow, &theWindow); else theErr = errAENoSuchObject; if (theErr == noErr) { theErr = MakeWindowObject(theWindow, &theObject); if (theErr == noErr) { if (reply->dataHandle) theErr = AEPutParamDesc(reply, keyAEResult, &theObject); AEDisposeDesc(&theObject); } } AEDisposeDesc(&theRecord); } else theErr = errAENoSuchObject; } } else theErr = errAEEventNotHandled; } AEEnd(); return theErr; } /* * HandleDelete(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the delete event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleDelete(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(reply, refCon) #endif ObjectTokenHandle theToken; OSErr theErr = noErr; ImageHandle theImage; AEDesc theObject; short i, count; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if ((theObject.descriptorType == cWindow) || (theObject.descriptorType == cDocument)) { count = (*theToken)->count; for (i = count - 1; i >= 0; i--) { if (theErr == noErr) theErr = DoCloseWindow((WindowPtr)(*theToken)->object[i], gThePrefs.restoreColors); } } else if (theObject.descriptorType == cPixelMap) { count = (*theToken)->count; for (i = 0; i < count; i++) { theImage = FindImage((WindowPtr)(*theToken)->object[i]); if (theImage) KillGWorld(theImage); else { theErr = errAENoSuchObject; break; } } } else theErr = errAEEventNotHandled; AEDisposeDesc(&theObject); } AEEnd(); return theErr; } /* * HandleDoObjectsExist(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the do objects exist event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleDoObjectsExist(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif OSErr theErr = noErr; Boolean theResult; AEDesc theObject; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); theResult = (theErr == noErr); if (reply->dataHandle) theErr = AEPutParamPtr(reply, keyAEResult, typeBoolean, (void *)&theResult, sizeof(Boolean)); AEEnd(); return theErr; } /* * HandleGetData(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the get data event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleGetData(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif DescType **theTypes = nil, typeWanted; AEDesc theList, theObject, theData; ObjectTokenHandle theToken; short i, j, count, types; OSErr theErr = noErr; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { AEExtractTypeList(theEvent, keyAEObjectClass, &theTypes); types = (theTypes) ? GetHandleSize((Handle)theTypes) / sizeof(DescType) : 1; theToken = (ObjectTokenHandle)theObject.dataHandle; count = (*theToken)->count; if (count > 1) theErr = AECreateList(nil, 0, false, &theList); for (i = 0; i < count; i++) { theData.descriptorType = typeNull; for (j = 0; j < types; j++) { typeWanted = (theTypes) ? (*theTypes)[j] : typeWildCard; theErr = DoGetData(theObject.descriptorType, theToken, i, typeWanted, &theData); if (theErr == noErr) { if (reply->dataHandle) { if (count == 1) theErr = AEPutParamDesc(reply, keyAEResult, &theData); else theErr = AEPutDesc(&theList, i + 1, &theData); } AEDisposeDesc(&theData); break; } } if (j == types) theErr = errAECantSupplyType; if (theErr != noErr) break; } if (count > 1) { if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList); AEDisposeDesc(&theList); } AEDisposeDesc(&theObject); if (theTypes) DisposeHandle((Handle)theTypes); } AEEnd(); return theErr; } /* * DoGetData(theType, theToken, index, typeWanted, theData) * * Purpose: Dispatches the get data event to the appropriate handler * Inputs: theType = the object class whose data we want * theToken = the tokens for the objects * index = the index of the token we're interested in * typeWanted = the type we're looking to get back * theData = descriptor to put the data in * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ OSErr DoGetData(DescType theType, ObjectTokenHandle theToken, short index, DescType typeWanted, AEDesc *theData) { WindowPtr theWindow = (WindowPtr)(*theToken)->object[index]; OSErr theErr; switch (theType) { case typeNull: theErr = GetApplicationData(typeWanted, theData); break; case cWindow: theErr = GetWindowData(theWindow, typeWanted, theData); break; case cDocument: theErr = GetDocumentData(theWindow, typeWanted, theData); break; case cDrawingArea: theErr = GetDrawingAreaData(theWindow, typeWanted, theData); break; case cImage: theErr = GetImageData(theWindow, typeWanted, theData); break; case cFile: theErr = GetFileData(theWindow, typeWanted, theData); break; case cPixelMap: theErr = GetPixelMapData(theWindow, typeWanted, theData); break; case cSelection: theErr = GetSelectionData(theWindow, typeWanted, theData); break; case typeProperty: switch ((*theToken)->objclass) { case typeNull: theErr = GetAppPropertyData((*theToken)->property, typeWanted, theData); break; case cWindow: theErr = GetWinPropertyData(theWindow, (*theToken)->property, typeWanted, theData); break; case cDocument: theErr = GetDocPropertyData(theWindow, (*theToken)->property, typeWanted, theData); break; case cDrawingArea: theErr = GetDrawPropertyData(theWindow, (*theToken)->property, typeWanted, theData); break; case cImage: theErr = GetImagePropertyData(theWindow, (*theToken)->property, typeWanted, theData); break; case cFile: theErr = GetFilePropertyData(theWindow, (*theToken)->property, typeWanted, theData); break; case cPixelMap: theErr = GetPixelPropertyData(theWindow, (*theToken)->property, typeWanted, theData); break; case cSelection: theErr = GetSelPropertyData(theWindow, (*theToken)->property, typeWanted, theData); break; } break; default: theErr = errAEReadDenied; break; } return theErr; } /* * HandleGetDataSize(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the get data size event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleGetDataSize(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif AEDesc theList, theObject, theData; DescType **theTypes, typeWanted; ObjectTokenHandle theToken; short i, j, count, types; OSErr theErr = noErr; long theSize; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { AEExtractTypeList(theEvent, keyAEObjectClass, &theTypes); types = (theTypes) ? GetHandleSize((Handle)theTypes) / sizeof(DescType) : 1; theToken = (ObjectTokenHandle)theObject.dataHandle; count = (*theToken)->count; if (count > 1) theErr = AECreateList(nil, 0, false, &theList); for (i = 0; i < count; i++) { theData.descriptorType = typeNull; for (j = 0; j < types; j++) { typeWanted = (theTypes) ? (*theTypes)[j] : typeWildCard; theErr = DoGetData(theObject.descriptorType, theToken, i, typeWanted, &theData); if (theErr == noErr) { theSize = GetHandleSize(theData.dataHandle); AEDisposeDesc(&theData); if (reply->dataHandle) { if (count == 1) theErr = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (void *)&theSize, sizeof(long)); else theErr = AEPutPtr(&theList, i + 1, typeLongInteger, (void *)&theSize, sizeof(long)); break; } } } if (j == types) theErr = errAECantSupplyType; if (theErr != noErr) break; } if (count > 1) { if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList); AEDisposeDesc(&theList); } AEDisposeDesc(&theObject); if (theTypes) DisposeHandle((Handle)theTypes); } AEEnd(); return theErr; } /* * HandleMove(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the move event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleMove(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif AEDesc theList, theObject, newObject; WindowPtr theWindow, behindWindow; ObjectTokenHandle theToken; OSErr theErr = noErr; short i, count; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if ((theObject.descriptorType == cWindow) || (theObject.descriptorType == cDocument)) { count = (*theToken)->count; theErr = AEExtractInsertionLoc(theEvent, keyAEInsertHere, &behindWindow); if (theErr == noErr) { if (count > 1) theErr = AECreateList(nil, 0, false, &theList); for (i = 0; i < count; i++) { if (theErr == noErr) { theWindow = (WindowPtr)(*theToken)->object[i]; theErr = DoMoveWindow(theWindow, behindWindow); if (theErr == noErr) theErr = MakeWindowObject(theWindow, &newObject); if (theErr == noErr) { if (count == 1) { if (reply->dataHandle) theErr = AEPutParamDesc(reply, keyAEResult, &newObject); } else theErr = AEPutDesc(&theList, i + 1, &newObject); } AEDisposeDesc(&newObject); behindWindow = theWindow; } } if (count > 1) { if (reply->dataHandle) AEPutParamDesc(reply, keyAEResult, &theList); AEDisposeDesc(&theList); } } else theErr = errAEEventFailed; } else theErr = errAECantHandleClass; AEDisposeDesc(&theObject); } AEEnd(); return theErr; } /* * HandleSave(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the save event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleSave(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(reply, refCon) #endif Boolean preview, palette, icons; ObjectTokenHandle theToken; OSErr theErr = noErr; ImageHandle theImage; AEDesc theObject; DescType theType; FSSpec theSpec; short cropWhat; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if ((theObject.descriptorType == cDocument) || (theObject.descriptorType == cWindow)) { if ((*theToken)->count == 1) { theImage = FindImage((WindowPtr)(*theToken)->object[0]); if (theImage) { theErr = AEExtractAlias(theEvent, keyAEFile, &theSpec); if (theErr != noErr) theSpec = (*theImage)->file; theErr = AEExtractType(theEvent, keyAEFileType, &theType); if (theErr != noErr) theType = ((*theImage)->compression == kJPEGCompression && gThePrefs.savePICT) ? kPICTType : (*theImage)->format->inType; theErr = AEExtractBoolean(theEvent, keyCreatePreview, &preview); if (theErr != noErr) preview = gThePrefs.savePrev; theErr = AEExtractBoolean(theEvent, keySaveQuant, &palette); if (theErr != noErr) palette = (*theImage)->qpalette && (theType == kPICTType || (*theImage)->format->doesColors) && ((gThePrefs.saveQuant == sqOnly && !(*theImage)->ipalette) || gThePrefs.saveQuant == sqAlways); theErr = AEExtractBoolean(theEvent, keyMakeIcons, &icons); if (theErr != noErr) icons = gThePrefs.makeIcons; if (theErr == noErr) theErr = AEExtractShort(theEvent, keyCropWhat, &cropWhat); if (theErr != noErr || !AntsHaveSelection((*theImage)->ants)) cropWhat = kCropNothing; StartSpinning(); theErr = DoSaveDocument(theImage, &theSpec, theType, preview, palette, icons, cropWhat); StopSpinning(&qd.arrow); } else theErr = errAENoSuchObject; } else theErr = errAENotASingleObject; } else theErr = errAECantHandleClass; AEDisposeDesc(&theObject); } AEEnd(); return theErr; } /* * HandleSetData(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the set data event * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleSetData(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(reply, refCon) #endif ObjectTokenHandle theToken; AEDesc theObject, theData, dataObject; OSErr theErr = noErr; short i, count; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theData.descriptorType = typeNull; theErr = AEGetParamDesc(theEvent, keyAEData, typeWildCard, &theData); if ((theErr == noErr) && (theData.descriptorType == typeObjectSpecifier)) { theErr = AEExtractObject(&theData, 0, &dataObject); AEDisposeDesc(&theData); if (theErr == noErr) { theToken = (ObjectTokenHandle)dataObject.dataHandle; if ((*theToken)->count == 1) theErr = DoGetData(dataObject.descriptorType, theToken, 0, typeWildCard, &theData); else theErr = errAENotASingleObject; } } if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; count = (*theToken)->count; for (i = 0; i < count; i++) if (theErr == noErr) theErr = DoSetData(theObject.descriptorType, theToken, i, &theData); AEDisposeDesc(&theData); } AEDisposeDesc(&theObject); } AEEnd(); return theErr; } /* * DoSetData(theType, theToken, index, typeWanted, theData) * * Purpose: Dispatches the set data event to the appropriate handler * Inputs: theType = the object class whose data we want to set * theToken = the tokens for the objects * index = the index of the token we're interested in * theData = descriptor to get the data from * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ OSErr DoSetData(DescType theType, ObjectTokenHandle theToken, short index, AEDesc *theData) { WindowPtr theWindow = (WindowPtr)(*theToken)->object[index]; OSErr theErr; switch (theType) { case typeProperty: switch ((*theToken)->objclass) { case typeNull: theErr = SetAppPropertyData((*theToken)->property, theData); break; case cWindow: theErr = SetWinPropertyData(theWindow, (*theToken)->property, theData); break; case cDocument: theErr = SetDocPropertyData(theWindow, (*theToken)->property, theData); break; case cDrawingArea: theErr = SetDrawPropertyData(theWindow, (*theToken)->property, theData); break; case cImage: theErr = SetImagePropertyData(theWindow, (*theToken)->property, theData); break; case cFile: theErr = SetFilePropertyData(theWindow, (*theToken)->property, theData); break; case cPixelMap: theErr = SetPixelPropertyData(theWindow, (*theToken)->property, theData); break; case cSelection: theErr = SetSelPropertyData(theWindow, (*theToken)->property, theData); break; } break; default: theErr = errAEWriteDenied; break; } return theErr; } \ No newline at end of file diff --git a/Source/C/CustomCopyBits.c b/Source/C/CustomCopyBits.c new file mode 100644 index 0000000..23c2dfa --- /dev/null +++ b/Source/C/CustomCopyBits.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "CustomCopyBits.h" #include "QuickDrawUtils.h" #if !USE_ASM #if __MWERKS__ #define kStackRowWidth 1024 #else #define kStackRowWidth 1750 #endif #endif //===================================================================================== // CopyData: structure for passing data between the C and assembly language portions of // the code //===================================================================================== #if USE_ASM typedef struct DitherErrors { short red; short green; short blue; } DitherErrors, *DitherErrorsPtr; typedef struct RgnBuffer { short yCount; short zero; short buffer[127]; } RgnBuffer, *RgnBufferPtr; #else typedef struct DitherErrors { long red; long green; long blue; } DitherErrors, *DitherErrorsPtr; typedef struct RgnBuffer { long yCount; long zero; long buffer[127]; } RgnBuffer, *RgnBufferPtr; #endif typedef (*DitherToDestPtr)(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns); typedef struct CopyData { // Needed for all copy routines ColorSpec *ctAddr; // color table address uchar *itAddr; // inverse color table address DitherErrorsPtr evenAddr,// even dithering buffer oddAddr; // odd dithering buffer DitherToDestPtr even, // address of even row dithering routine odd; // address of odd row dithering routine short *errTable; // address of dithering table long srcRow, // row bytes in source pixmap dstRow; // row bytes in destination pixmap Ptr srcBase, // base address of source pixmap dstBase; // base address of destination pixmap #if USE_ASM short rgnBuffer[512], // buffer for holding region data width, // total width of image height, // total height of image evodd; // word holding the even/odd row status #else long rgnBuffer[512], width, // total width of image height, // total height of image evodd; // word holding the even/odd row status #endif RgnHandle theRgn; // handle to the clipping region Rect boxRect; // outer rect of the region // Needed only for CopyScaled routines #if USE_ASM short srcHeight, // height of the source rectangle srcWidth, // width of same dstHeight, // height of the destination rectangle dstWidth, // width of same xRemainder, // starting remainder in x yRemainder, // starting remainder in y columns, // internal counter for columns rows; // internal counter for rows #else long srcHeight, // height of the source rectangle srcWidth, // width of same dstHeight, // height of the destination rectangle dstWidth, // width of same xRemainder, // starting remainder in x yRemainder, // starting remainder in y columns, // internal counter for columns rows; // internal counter for rows #endif Ptr outputAddr, // internal holder for destination address sTable[6]; // pointers into the scaling table } CopyData, *CopyDataPtr, **CopyDataHandle; //===================================================================================== // Global variables local to this module //===================================================================================== static Point gZeroPoint = { 0, 0 }; static RgnHandle gTheRgn = nil; static CopyData gCopyData; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static void InitCopyData(void); #if !USE_ASM static void CopyUnscaledFrom32(CopyDataPtr theData); static void CopyReallyFastScaledFrom32(CopyDataPtr theData); static void CopyFastScaledFrom32(CopyDataPtr theData); static void CopyScaledFrom32(CopyDataPtr theData); static void CopyTo32(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns); static void DitherCopyTo16Even(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns); static void DitherCopyTo16Odd(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns); static void DitherCopyTo8Even(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns); static void DitherCopyTo8Odd(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns); static short *InitRegion(RgnPtr rgn, RgnBufferPtr rgnBuffer, Rect *boxRect); static short *UpdateRegion(short *rgnData, RgnBufferPtr rgnBuffer, Rect *boxRect); #elif THINK_C static void CopyUnscaledFrom32(CopyDataPtr theData); static void CopyReallyFastScaledFrom32(CopyDataPtr theData); static void CopyScaledFrom32(CopyDataPtr theData); static void CopyFastScaledFrom32(CopyDataPtr theData); static void CopyTo32(void); static void DitherCopyTo16Even(void); static void DitherCopyTo16Odd(void); static void DitherCopyTo8Even(void); static void DitherCopyTo8Odd(void); static void InitRegion(void); static void UpdateRegion(void); #else extern void CopyUnscaledFrom32(CopyDataPtr theData); extern void CopyReallyFastScaledFrom32(CopyDataPtr theData); extern void CopyScaledFrom32(CopyDataPtr theData); extern void CopyFastScaledFrom32(CopyDataPtr theData); extern void CopyTo32(void); extern void DitherCopyTo16Even(void); extern void DitherCopyTo16Odd(void); extern void DitherCopyTo8Even(void); extern void DitherCopyTo8Odd(void); #endif //===================================================================================== // void InitCopyData(void) // // One-time initialization of several static fields in the global CopyData structure // // External calls: none //===================================================================================== void InitCopyData(void) { gCopyData.theRgn = gTheRgn = NewRgn(); gCopyData.errTable = gErrTable; gCopyData.sTable[0] = (Ptr)gScaleTable; gCopyData.sTable[1] = gCopyData.sTable[0] + (3 << 8); gCopyData.sTable[2] = gCopyData.sTable[1] + (4 << 8); gCopyData.sTable[3] = gCopyData.sTable[2] + (5 << 8); gCopyData.sTable[4] = gCopyData.sTable[3] + (6 << 8); gCopyData.sTable[5] = gCopyData.sTable[4] + (7 << 8); } //===================================================================================== // void DoCustomCopy(PixMap *src, PixMap *dst, Rect *srcRect, Rect *dstRect, // Boolean fast, short depth) // // Performs the appropriate variation of our custom CopyBits routine, according to the // fast, depth, and srcRect/dstRect parameters. // // External calls: GlobalRect, GlobalRgn, Width, Height //===================================================================================== void DoCustomCopy(PixMap *src, PixMap *dst, Rect *srcRect, Rect *dstRect, Boolean fast, short depth) { GDHandle theGDevice = GetGDevice(); Boolean onScreen = ((*theGDevice)->gdFlags & (1L << screenActive)) != 0; char mode = true32b; CTabHandle theCTab; ITabHandle theITab; Rect globDRect; // Initialize the global copy data, if necessary if (!gTheRgn) InitCopyData(); // Initialize the even/odd function pointers switch (depth) { case 32: gCopyData.even = (DitherToDestPtr)CopyTo32; gCopyData.odd = (DitherToDestPtr)CopyTo32; break; case 16: gCopyData.even = (DitherToDestPtr)DitherCopyTo16Even; gCopyData.odd = (DitherToDestPtr)DitherCopyTo16Odd; break; case 8: gCopyData.even = (DitherToDestPtr)DitherCopyTo8Even; gCopyData.odd = (DitherToDestPtr)DitherCopyTo8Odd; break; } // Globalize the destination rectangle globDRect = *dstRect; if (onScreen) GlobalRect(&globDRect, qd.thePort); // Calculate the global intersection of the clipRgn, visRgn, and dstRect // Note that we set the evodd value while the rectangle is still *local* RectRgn(gCopyData.theRgn, dstRect); SectRgn(qd.thePort->clipRgn, gCopyData.theRgn, gCopyData.theRgn); SectRgn(qd.thePort->visRgn, gCopyData.theRgn, gCopyData.theRgn); gCopyData.evodd = (*gCopyData.theRgn)->rgnBBox.top; if (onScreen) GlobalRgn(gCopyData.theRgn, qd.thePort); // If the resulting region is empty, return before we do anything if (EmptyRgn(gCopyData.theRgn)) return; // Use the resulting region bounding box as our real dst rect gCopyData.boxRect = (*gCopyData.theRgn)->rgnBBox; gCopyData.height = Height(&gCopyData.boxRect); gCopyData.width = Width(&gCopyData.boxRect); // Calculate widths and heights gCopyData.dstHeight = Height(dstRect); gCopyData.dstWidth = Width(dstRect); gCopyData.srcHeight = Height(srcRect); gCopyData.srcWidth = Width(srcRect); // Get the base addresses, offset by the dst and src rectangles gCopyData.srcBase = GetPixBaseAddr(&src); gCopyData.dstBase = GetPixBaseAddr(&dst); gCopyData.srcRow = src->rowBytes & 0x3fff; gCopyData.dstRow = dst->rowBytes & 0x3fff; gCopyData.srcBase += gCopyData.srcRow * ((srcRect->top - src->bounds.top) + ((long)(gCopyData.boxRect.top - globDRect.top) * (long)gCopyData.srcHeight / (long)gCopyData.dstHeight)); gCopyData.srcBase += ((srcRect->left - src->bounds.left) + (long)(gCopyData.boxRect.left - globDRect.left) * (long)gCopyData.srcWidth / (long)gCopyData.dstWidth) << 2; gCopyData.dstBase += gCopyData.dstRow * (gCopyData.boxRect.top - dst->bounds.top) + (((long)(gCopyData.boxRect.left - dst->bounds.left) * (long)dst->pixelSize) >> 3); // Calculate initial remainders for the source at this point gCopyData.xRemainder = gCopyData.dstWidth - ((long)(gCopyData.boxRect.left - globDRect.left) * (long)gCopyData.srcWidth) % (long)gCopyData.dstWidth; #if USE_ASM gCopyData.xRemainder = ((long)gCopyData.xRemainder << 10) / (long)gCopyData.srcWidth; #else gCopyData.xRemainder = ((long)gCopyData.xRemainder << 16) / (long)gCopyData.srcWidth; #endif gCopyData.yRemainder = gCopyData.dstHeight - ((long)(gCopyData.boxRect.top - globDRect.top) * (long)gCopyData.srcHeight) % (long)gCopyData.dstHeight; #if USE_ASM gCopyData.yRemainder = ((long)gCopyData.yRemainder << 10) / (long)gCopyData.srcHeight; #else gCopyData.yRemainder = ((long)gCopyData.yRemainder << 16) / (long)gCopyData.srcHeight; #endif // Get handles to the color tables theCTab = (*(*theGDevice)->gdPMap)->pmTable; theITab = (*theGDevice)->gdITable; // Shield the cursor if necessary and get the final pointers if (onScreen) ShieldCursor(&gCopyData.boxRect, gZeroPoint); if (theITab) gCopyData.itAddr = (*theITab)->iTTable; if (theCTab) gCopyData.ctAddr = (*theCTab)->ctTable; // Do the copy SwapMMUMode(&mode); if (EqualSizeRect(srcRect, dstRect)) CopyUnscaledFrom32(&gCopyData); else if (fast) CopyReallyFastScaledFrom32(&gCopyData);//CopyFastScaledFrom32(&gCopyData); else CopyScaledFrom32(&gCopyData); SwapMMUMode(&mode); if (onScreen) ShowCursor(); } #if !USE_ASM //===================================================================================== // Generic C substitutes for the assembly functions defined below. //===================================================================================== static void CopyUnscaledFrom32(CopyDataPtr theData) { #include "CopyUnscaledFrom32.c" } static void CopyReallyFastScaledFrom32(CopyDataPtr theData) { #include "CopyReallyFastScaledFrom32.c" } static void CopyFastScaledFrom32(CopyDataPtr theData) { #include "CopyFastScaledFrom32.c" } static void CopyScaledFrom32(CopyDataPtr theData) { #include "CopyScaledFrom32.c" } static void CopyTo32(ulong *srcRow, void *dstRow, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns) { #include "CopyTo32.c" } static void DitherCopyTo16Even(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns) { #include "DitherCopyTo16Even.c" } static void DitherCopyTo16Odd(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns) { #include "DitherCopyTo16Odd.c" } static void DitherCopyTo8Even(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns) { #include "DitherCopyTo8Even.c" } static void DitherCopyTo8Odd(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, long *rgnBuffer, short *errorMap, long columns) { #include "DitherCopyTo8Odd.c" } static short *InitRegion(RgnPtr rgn, RgnBufferPtr rgnBuffer, Rect *boxRect) { #include "InitRegion.c" } static short *UpdateRegion(short *rgnData, RgnBufferPtr rgnBuffer, Rect *boxRect) { #include "UpdateRegion.c" } #elif THINK_C //===================================================================================== // Assembly language interfaces for THINK C; here we define the offsets of all fields // within the CopyData structure, and then provide C function wrappers around asm { } // statements that #include the actual assembly code. In MPW, we just need to compile // CustomCopyBits.a to get the assembly routines. //===================================================================================== #define ctAddr offsetof(CopyData, ctAddr) /* 0 */ #define itAddr offsetof(CopyData, itAddr) /* 4 */ #define evenAddr offsetof(CopyData, evenAddr) /* 8 */ #define oddAddr offsetof(CopyData, oddAddr) /* 12 */ #define even offsetof(CopyData, even) /* 16 */ #define odd offsetof(CopyData, odd) /* 20 */ #define errTable offsetof(CopyData, errTable) /* 24 */ #define srcRow offsetof(CopyData, srcRow) /* 28 */ #define dstRow offsetof(CopyData, dstRow) /* 32 */ #define srcBase offsetof(CopyData, srcBase) /* 36 */ #define dstBase offsetof(CopyData, dstBase) /* 40 */ #define rgnBuffer offsetof(CopyData, rgnBuffer) /* 44 */ #define width offsetof(CopyData, width) /* 1068 */ #define height offsetof(CopyData, height) /* 1070 */ #define evodd offsetof(CopyData, evodd) /* 1072 */ #define theRgn offsetof(CopyData, theRgn) /* 1074 */ #define boxRect offsetof(CopyData, boxRect) /* 1078 */ #define srcHeight offsetof(CopyData, srcHeight) /* 1086 */ #define srcWidth offsetof(CopyData, srcWidth) /* 1088 */ #define dstHeight offsetof(CopyData, dstHeight) /* 1090 */ #define dstWidth offsetof(CopyData, dstWidth) /* 1092 */ #define xRemainder offsetof(CopyData, xRemainder)/* 1094 */ #define yRemainder offsetof(CopyData, yRemainder)/* 1096 */ #define columns offsetof(CopyData, columns) /* 1098 */ #define rows offsetof(CopyData, rows) /* 1100 */ #define outputAddr offsetof(CopyData, outputAddr)/* 1102 */ #define sTable offsetof(CopyData, sTable) /* 1106 */ void CopyUnscaledFrom32(CopyDataPtr theData) { asm { #include "CopyUnscaledFrom32.a" } } void CopyScaledFrom32(CopyDataPtr theData) { asm { #include "CopyScaledFrom32.a" } } void CopyReallyFastScaledFrom32(CopyDataPtr theData) { asm { #include "CopyReallyFastScaledFrom32.a" } } void CopyFastScaledFrom32(CopyDataPtr theData) { asm { #include "CopyFastScaledFrom32.a" } } void CopyTo32(void) { asm { #include "CopyTo32.a" } } void DitherCopyTo16Even(void) { asm { #include "DitherCopyTo16Even.a" } } void DitherCopyTo16Odd(void) { asm { #include "DitherCopyTo16Odd.a" } } void DitherCopyTo8Even(void) { asm { #include "DitherCopyTo8Even.a" } } void DitherCopyTo8Odd(void) { asm { #include "DitherCopyTo8Odd.a" } } void InitRegion(void) { asm { #include "InitRegion.a" } } void UpdateRegion(void) { asm { #include "UpdateRegion.a" } } #endif \ No newline at end of file diff --git a/Source/C/DecodeDummyRow.c b/Source/C/DecodeDummyRow.c new file mode 100644 index 0000000..1f090f4 --- /dev/null +++ b/Source/C/DecodeDummyRow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void DecodeDummyRow(GIFDataPtr theData) ushort *parent = (ushort *)theData->tree; uchar *code = (uchar *)(parent + 4096); short i, j, currentCode, oldCode; if (!theData->dest) { theData->charSize = *theData->src++; gCodeSize = theData->charSize + 1; gStack = theData->stack; gBytesLeft = gBitsInBuffer = gBitBuffer = 0; gTreeSize = (1 << theData->charSize); gClearCode = gTreeSize++; gEndCode = gTreeSize++; gInput = theData->src; theData->theReturn = true; return; } for (i = 0; i < theData->width; i++) { if (gStack != theData->stack) { --gStack; continue; } while (gCodeSize > gBitsInBuffer) { if (!gBytesLeft) { gBytesLeft = *gInput++; if (!gBytesLeft) { theData->theReturn = true; return; } } gBytesLeft--; gBitBuffer |= (ulong)*gInput++ << gBitsInBuffer; gBitsInBuffer += 8; } currentCode = gBitBuffer & ((1 << gCodeSize) - 1); gBitBuffer >>= gCodeSize; gBitsInBuffer -= gCodeSize; if (currentCode == gEndCode) { theData->theReturn = true; return; } else if (currentCode == gClearCode) { gCodeSize = theData->charSize + 1; gTreeSize = gEndCode + 1; do { while (gCodeSize > gBitsInBuffer) { if (!gBytesLeft) { gBytesLeft = *gInput++; if (!gBytesLeft) { theData->theReturn = true; return; } } gBytesLeft--; gBitBuffer |= (ulong)*gInput++ << gBitsInBuffer; gBitsInBuffer += 8; } currentCode = gBitBuffer & ((1 << gCodeSize) - 1); gBitBuffer >>= gCodeSize; gBitsInBuffer -= gCodeSize; } while (currentCode == gClearCode); gFirstCode = gLastCode = currentCode; continue; } oldCode = currentCode; if (currentCode > gTreeSize) { theData->end = nil; break; } else if (currentCode == gTreeSize) { *gStack++ = gFirstCode; currentCode = gLastCode; } for (j = currentCode; j >= gClearCode; j = parent[j]) *gStack++ = code[j]; gFirstCode = j; if (gTreeSize != 4096) { code[gTreeSize] = gFirstCode; parent[gTreeSize] = gLastCode; if ((++gTreeSize >= (1 << gCodeSize)) && (gCodeSize != 12)) gCodeSize++; } gLastCode = oldCode; } theData->theReturn = false; if (gInput > theData->end) theData->end = nil; \ No newline at end of file diff --git a/Source/C/DecodeRow.c b/Source/C/DecodeRow.c new file mode 100644 index 0000000..a23ab52 --- /dev/null +++ b/Source/C/DecodeRow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void DecodeRow(GIFDataPtr theData) ushort *parent = (ushort *)theData->tree; uchar *code = (uchar *)(parent + 4096); short i, j, currentCode, oldCode; if (!theData->dest) { theData->charSize = *theData->src++; gCodeSize = theData->charSize + 1; gStack = theData->stack; gBytesLeft = gBitsInBuffer = gBitBuffer = 0; gTreeSize = (1 << theData->charSize); gClearCode = gTreeSize++; gEndCode = gTreeSize++; gInput = theData->src; theData->theReturn = true; return; } for (i = 0; i < theData->width; i++) { if (gStack != theData->stack) { *theData->dest++ = *(--gStack); continue; } while (gCodeSize > gBitsInBuffer) { if (!gBytesLeft) { gBytesLeft = *gInput++; if (!gBytesLeft) { theData->theReturn = true; return; } } gBytesLeft--; gBitBuffer |= (ulong)*gInput++ << gBitsInBuffer; gBitsInBuffer += 8; } currentCode = gBitBuffer & ((1 << gCodeSize) - 1); gBitBuffer >>= gCodeSize; gBitsInBuffer -= gCodeSize; if (currentCode == gEndCode) { theData->theReturn = true; return; } else if (currentCode == gClearCode) { gCodeSize = theData->charSize + 1; gTreeSize = gEndCode + 1; do { while (gCodeSize > gBitsInBuffer) { if (!gBytesLeft) { gBytesLeft = *gInput++; if (!gBytesLeft) { theData->theReturn = true; return; } } gBytesLeft--; gBitBuffer |= (ulong)*gInput++ << gBitsInBuffer; gBitsInBuffer += 8; } currentCode = gBitBuffer & ((1 << gCodeSize) - 1); gBitBuffer >>= gCodeSize; gBitsInBuffer -= gCodeSize; } while (currentCode == gClearCode); *theData->dest++ = gFirstCode = gLastCode = currentCode; continue; } oldCode = currentCode; if (currentCode > gTreeSize) { theData->end = nil; break; } else if (currentCode == gTreeSize) { *gStack++ = gFirstCode; currentCode = gLastCode; } for (j = currentCode; j >= gClearCode; j = parent[j]) *gStack++ = code[j]; *theData->dest++ = gFirstCode = j; if (gTreeSize != 4096) { code[gTreeSize] = gFirstCode; parent[gTreeSize] = gLastCode; if ((++gTreeSize >= (1 << gCodeSize)) && (gCodeSize != 12)) gCodeSize++; } gLastCode = oldCode; } theData->theReturn = false; if (gInput > theData->end) theData->end = nil; \ No newline at end of file diff --git a/Source/C/DialogUtils.c b/Source/C/DialogUtils.c new file mode 100644 index 0000000..2c639b9 --- /dev/null +++ b/Source/C/DialogUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // void IsDialogWindow(WindowPtr theWindow) // // Returns true if the window is a dialog window. // // External calls: none //===================================================================================== extern Boolean IsDialogWindow(WindowPtr theWindow) { return theWindow ? (WindowKind(theWindow) == dialogKind) : false; } /* * CenterWindow(theWindow) * * Purpose: Determines where a centered dialog should be placed * Inputs: theWindow = a pointer to the dialog window * Returns: the centered location * */ Point CenterWindow(WindowPtr theWindow) { short var = GetWVariant(theWindow), height = Height(&theWindow->portRect); Point thePos; Rect theRect; if (var != dBoxProc) height += gTitleBarHeight; switch (gThePrefs.openScreen) { case osDeepest: GetActiveRect(GetDeepMonitor(gThePrefs.pickColor), &theRect); break; case osLargest: GetActiveRect(GetBigMonitor(gThePrefs.pickColor), &theRect); break; case osMain: GetActiveRect(gMainMonitor, &theRect); break; } thePos.h = Width(&theRect) - Width(&theWindow->portRect); thePos.v = Height(&theRect) - height; thePos.h /= 2; thePos.v /= 3; thePos.h += theRect.left; thePos.v += theRect.top; if (var != dBoxProc) thePos.v += gTitleBarHeight; return thePos; } /* * GetMouseGDRect(theRect) * * Purpose: Gets the Rect of the device where the mouse is * Inputs: theRect = pointer to the rect to be filled * Returns: nothing * */ void GetMouseGDRect(Rect *theRect) { GDHandle theDevice = GetDeviceList(); Point thePoint = GlobalMouse(); *theRect = qd.screenBits.bounds; while (theDevice) { if (TestDeviceAttribute(theDevice, screenDevice) && TestDeviceAttribute(theDevice, screenActive) && PtInRect(thePoint, &(*theDevice)->gdRect)) { *theRect = (*theDevice)->gdRect; if (theDevice == GetMainDevice()) theRect->top += GetMBarHeight(); } theDevice = GetNextDevice(theDevice); } } /* * MouseCenterRect(theRect) * * Purpose: Centers the given Rect on the screen where the mouse is * Inputs: theRect = pointer to the rect to be filled * Returns: nothing * */ void MouseCenterRect(Rect *theRect) { Point thePoint = GlobalMouse(); GDHandle theDevice; Rect devRect; MySetRect(&devRect, thePoint.h, thePoint.v, thePoint.h + 1, thePoint.v + 1); theDevice = GetMaxDevice(&devRect); if (theDevice) { devRect = (*theDevice)->gdRect; OffsetRect(theRect, (Width(&devRect) - Width(theRect)) / 2 + devRect.left - theRect->left, (Height(&devRect) - Height(theRect)) / 3 + devRect.top - theRect->top); } } /* * CenterAlert(id) * * Purpose: Loads and centers the given alert resource * Inputs: id = the resource ID of the alert * Returns: the ID, to be passed to Alert() * */ short CenterAlert(short id) { Handle theHandle = GetResource('ALRT', id); if (theHandle) { HLock(theHandle); MouseCenterRect((Rect *)*theHandle); HUnlock(theHandle); } return id; } /* * CenterDialog(id) * * Purpose: Loads and centers the given dialog resource * Inputs: id = the resource ID of the dialog * Returns: the ID, to be passed to GetNewDialog() * */ short CenterDialog(short id) { Handle theHandle = GetResource('DLOG', id); if (theHandle) { HLock(theHandle); MouseCenterRect((Rect *)*theHandle); HUnlock(theHandle); } return id; } /* * CenterDialogWhere(id) * * Purpose: Loads and centers the given dialog resource * Inputs: id = the resource ID of the dialog * Returns: a point giving the location for the dialog * */ Point CenterDialogWhere(short id) { Handle theHandle = GetResource('DLOG', id); if (theHandle) { HLock(theHandle); MouseCenterRect((Rect *)*theHandle); HUnlock(theHandle); } return *(Point *)*theHandle; } extern void UpdateParamText(StringPtr string1, StringPtr string2, StringPtr string3, StringPtr string4) { static Str255 gOldString1 = "", gOldString4 = ""; WindowPtr theWindow = FWFrontWindow(); ParamText(string1, string2, string3, string4); if (theWindow && GetWRefCon(theWindow) == kProgressDialogID) { if (!EqualString(string1, gOldString1, true, true)) UpdateDialogItem(theWindow, progressText); if (!EqualString(string4, gOldString4, true, true)) UpdateDialogItem(theWindow, progressText2); } BlockMove(string1, gOldString1, *string1 + 1); BlockMove(string4, gOldString4, *string4 + 1); } extern short HandleDialogLetterKey(DialogPtr theDialog, char theChar) { short itemCount, itemType, theItem; Handle itemHandle; Str255 theTitle; Rect itemRect; long ticks; if (theChar > 'a') theChar -= 'a' - 'A'; itemCount = CountDITL(theDialog); for (theItem = 1; theItem <= itemCount; theItem++) { GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); if (itemType == (ctrlItem + btnCtrl)) { GetCTitle((ControlHandle)itemHandle, theTitle); if (theChar == theTitle[1]) { HiliteControl((ControlHandle)itemHandle, true); Delay(8, &ticks); HiliteControl((ControlHandle)itemHandle, false); return theItem; } } } return 0; } extern short HandleDialogCancelKey(DialogPtr theDialog) { Handle itemHandle; short itemType; Rect itemRect; long ticks; GetDItem(theDialog, 3, &itemType, &itemHandle, &itemRect); if (itemType == (ctrlItem + btnCtrl)) { HiliteControl((ControlHandle)itemHandle, true); Delay(8, &ticks); HiliteControl((ControlHandle)itemHandle, false); return kDialogCancel; } return 0; } extern short HandleDialogOKKey(DialogPtr theDialog) { Handle itemHandle; short itemType; Rect itemRect; long ticks; GetDItem(theDialog, 1, &itemType, &itemHandle, &itemRect); if (itemType == (ctrlItem + btnCtrl)) { HiliteControl((ControlHandle)itemHandle, true); Delay(8, &ticks); HiliteControl((ControlHandle)itemHandle, false); return kDialogOK; } return 0; } /* * GenericFilter(theDialog, theEvent, itemHit) * * Purpose: Generic filter returns item 1 for return/enter, and item 3 for Cmd-. * Inputs: theDialog = pointer to the dialog * theEvent = pointer to an event record * itemHit = the item number that was "hit" * Returns: true if we want ModalDialog to continue processing the event * */ pascal Boolean GenericFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit) { Boolean isCmdKey, isCancelKey, isOKKey, isDialogEvent = IsDialogEvent(theEvent); short theItem = 0; char theChar; if ((theEvent->what == updateEvt) && ((WindowPtr)theEvent->message == FWFrontWindow())) return false; switch (theEvent->what) { case activateEvt: if (isDialogEvent) HandleActivateDialog(theEvent); else HandleActivateEvent(theEvent); break; case updateEvt: if (isDialogEvent) HandleUpdateDialog(theEvent); else HandleUpdateEvent(theEvent); break; case diskEvt: HandleDiskEvent(theEvent); break; case keyDown: theChar = theEvent->message & charCodeMask; isCmdKey = (theEvent->modifiers & cmdKey) != 0; isCancelKey = (theChar == kEscapeChar) || (isCmdKey && theChar == '.'); isOKKey = (theChar == kReturnChar || theChar == kEnterChar); if ((theChar >= 'A' && theChar <= 'Z') || (theChar >= 'a' && theChar <= 'z')) theItem = HandleDialogLetterKey(theDialog, theChar); else if (isCancelKey) theItem = HandleDialogCancelKey(theDialog); else if (isOKKey) theItem = HandleDialogOKKey(theDialog); break; } if (theItem) *itemHit = theItem; return (theItem != 0); } /* * OutlineOK(theDialog, theItem) * * Purpose: Generic handler to outline the default (OK) button * Inputs: theDialog = pointer to the dialog * theItem = presumably the item number of the dummy user item * Returns: nothing * */ pascal void OutlineOK(DialogPtr theDialog, short theItem) { WindowPtr frontWindow = FWFrontWindow(); RGBColor grayColor, fgColor, bgColor; ControlHandle itemHandle; short itemType; short diameter; Rect itemRect; PushPort(); MySetPort((CGrafPtr)theDialog); GetDItem(theDialog, theItem - 1, &itemType, (Handle *)&itemHandle, &itemRect); if ((diameter = (itemRect.bottom - itemRect.top) / 2) < 16) diameter = 16; PenSize(3, 3); InsetRect(&itemRect, -4, -4); if ((*itemHandle)->contrlHilite == 255 || theDialog != frontWindow || gInBackground) { GetBackColor(&bgColor); GetForeColor(&fgColor); grayColor = fgColor; GetGray(GetGDevice(), &bgColor, &grayColor); RGBForeColor(&grayColor); FrameRoundRect(&itemRect, diameter, diameter); RGBForeColor(&fgColor); } else FrameRoundRect(&itemRect, diameter, diameter); PopPort(); } extern pascal void PopUpMenuBox(DialogPtr theDialog, short theItem) { RgnHandle minusRgn, oldClip; Handle itemHandle; short itemType; Rect itemRect; if (minusRgn = NewRgn()) { if (oldClip = NewRgn()) { GetClip(oldClip); ClipRect(&theDialog->portRect); GetDItem(theDialog, theItem - 1, &itemType, &itemHandle, &itemRect); RectRgn(minusRgn, &itemRect); DiffRgn(theDialog->clipRgn, minusRgn, theDialog->clipRgn); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); PenPat(&qd.gray); PenSize(1, 1); FrameRect(&itemRect); PenPat(&qd.black); SetClip(oldClip); DisposeRgn(oldClip); } DisposeRgn(minusRgn); } } /* * LineItem(theDialog, theItem) * * Purpose: Generic handler to draw a line in a dialog box * Inputs: theDialog = pointer to the dialog * theItem = presumably the item number of the line item * Returns: nothing * */ pascal void LineItem(DialogPtr theDialog, short theItem) { Handle itemHandle; short itemType; Rect itemRect; PushPort(); MySetPort((CGrafPtr)theDialog); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); PenSize(1, 1); MoveTo(itemRect.left, itemRect.top); if ((itemRect.right - itemRect.left) < (itemRect.bottom - itemRect.top)) LineTo(itemRect.left, itemRect.bottom); else LineTo(itemRect.right, itemRect.top); PopPort(); } /* * SetItemHandle(theDialog, theItem, newHandle) * * Purpose: Change the handle of a dialog item * Inputs: theDialog = pointer to the dialog * theItem = the item number we're interested in * newHandle = the handle we'd like to change to * Returns: nothing * */ void SetItemHandle(DialogPtr theDialog, short theItem, Handle newHandle) { Handle itemHandle; short itemType; Rect itemRect; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); SetDItem(theDialog, theItem, itemType, newHandle, &itemRect); } /* * DisableDControl(theDialog, theItem) * * Purpose: Disables the control of a particular dialog item * Inputs: theDialog = pointer to the dialog * theItem = the item number we're interested in * Returns: nothing * */ void DisableDControl(DialogPtr theDialog, short theItem) { PenState oldState; Handle itemHandle; short itemType; Rect itemRect; PushPort(); MySetPort((CGrafPtr)theDialog); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); itemType &= 0x7f; if (itemType == editText || itemType == statText) { Boolean bw = !(((CGrafPtr)theDialog)->portVersion & 0x8000) || (*((CGrafPtr)theDialog)->portPixMap)->pixelSize == 1; RGBColor fgColor; FontInfo theInfo; Str255 theText; if (itemRect.left > 8191) OffsetRect(&itemRect, -16384, 0); HideDItem(theDialog, theItem); GetIText(itemHandle, theText); GetFontInfo(&theInfo); TextMode(grayishTextOr); MoveTo(itemRect.left + 1, itemRect.top + theInfo.ascent); DrawString(theText); TextMode(srcCopy); if (itemType == editText) { GetPenState(&oldState); PenSize(1, 1); PenMode(srcOr); if (bw) PenPat(&qd.gray); else { RGBColor grayColor, bgColor; GetBackColor(&bgColor); GetForeColor(&fgColor); grayColor = fgColor; GetGray(GetGDevice(), &bgColor, &grayColor); RGBForeColor(&grayColor); } InsetRect(&itemRect, -3, -3); FrameRect(&itemRect); if (!bw) RGBForeColor(&fgColor); else SetPenState(&oldState); } } else HiliteControl((ControlHandle)itemHandle, 255); PopPort(); } /* * EnableDControl(theDialog, theItem) * * Purpose: Enables the control of a particular dialog item * Inputs: theDialog = pointer to the dialog * theItem = the item number we're interested in * Returns: nothing * */ void EnableDControl(DialogPtr theDialog, short theItem) { Handle itemHandle; short itemType; Rect itemRect; PushPort(); MySetPort((CGrafPtr)theDialog); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); itemType &= 0x7f; if (itemType == editText || itemType == statText) ShowDItem(theDialog, theItem); else HiliteControl((ControlHandle)itemHandle, 0); PopPort(); } /* * SetDCtlValue(theDialog, theItem, theValue) * * Purpose: Sets the value of the control of a particular dialog item * Inputs: theDialog = pointer to the dialog * theItem = the item number we're interested in * theValue = the new value for that control * Returns: nothing * */ void SetDCtlValue(DialogPtr theDialog, short theItem, short theValue) { Handle itemHandle; short itemType; Rect itemRect; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); SetCtlValue((ControlHandle)itemHandle, theValue); } /* * GetDCtlValue(theDialog, theItem, theValue) * * Purpose: Gets the value of the control of a particular dialog item * Inputs: theDialog = pointer to the dialog * theItem = the item number we're interested in * Returns: the value of the control * */ short GetDCtlValue(DialogPtr theDialog, short theItem) { Handle itemHandle; short itemType; Rect itemRect; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); return GetCtlValue((ControlHandle)itemHandle); } /* * SetDIText(theDialog, theItem, theText) * * Purpose: Sets the text of an editable text dialog item * Inputs: theDialog = pointer to the dialog * theItem = the item number we're interested in * theText = a pointer to the new text * Returns: nothing * */ void SetDIText(DialogPtr theDialog, short theItem, Str255 theText) { Handle itemHandle; short itemType; Rect itemRect; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); SetIText(itemHandle, theText); } /* * GetDIText(theDialog, theItem, theText) * * Purpose: Gets the text of an editable text dialog item * Inputs: theDialog = pointer to the dialog * theItem = the item number we're interested in * theText = a pointer to the text field * Returns: nothing * */ void GetDIText(DialogPtr theDialog, short theItem, Str255 theText) { Handle itemHandle; short itemType; Rect itemRect; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); GetIText(itemHandle, theText); } void UpdateDialogItem(DialogPtr theDialog, short theItem) { Handle itemHandle; RgnHandle theRgn; short itemType; Rect itemRect; if (theRgn = NewRgn()) { PushPort(); MySetPort((CGrafPtr)theDialog); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); RectRgn(theRgn, &itemRect); UpdateDialog(theDialog, theRgn); PopPort(); DisposeRgn(theRgn); } } \ No newline at end of file diff --git a/Source/C/DitherCopyTo16Even.c b/Source/C/DitherCopyTo16Even.c new file mode 100644 index 0000000..cb16f2d --- /dev/null +++ b/Source/C/DitherCopyTo16Even.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void DitherCopyTo16Even(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, // DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, // short *rgnBuffer, uchar *errorMap, short columns) #if applec #pragma unused(iTable, cTable) #endif // internals: ulong *src = srcRow; // pointer to the 32-bit source row ushort *dst = (ushort *)dstRowStart; // pointer to the 16-bit destination row ulong pixel; // scratch for the current pixel long red; // red scratch area long green; // green scratch area long blue; // blue scratch area long red2; // 2 * the red error; used for fast calculations long green2; // 2 * the green error long blue2; // 2 * the blue error long rgnCol; // region column counter // initialize our counters and clear out next row red = green = blue = 0; oBuffer->red = oBuffer->green = oBuffer->blue = 0; // set up the region column counter if (!(rgnCol = *rgnBuffer++)) rgnCol -= *rgnBuffer++; // begin main loop here while (columns--) { // combine the accumulated errors and round to a pixel value red += eBuffer->red + 8; red >>= 4; red = errorMap[red]; green += eBuffer->green + 8; green >>= 4; green = errorMap[green]; blue += eBuffer->blue + 8; blue >>= 4; blue = errorMap[blue]; eBuffer++; // offset the current pixel by the errors pixel = *src++; blue += pixel & 0xff; pixel >>= 8; green += pixel & 0xff; pixel >>= 8; red += pixel & 0xff; // check for overflows and handle them if (red > 255) red = 255; else if (red < 0) red = 0; if (blue > 255) blue = 255; else if (blue < 0) blue = 0; if (green > 255) green = 255; else if (green < 0) green = 0; // get the inverse color table entry pixel = red >> 3; pixel <<= 5; pixel += green >> 3; pixel <<= 5; pixel += blue >> 3; // determine whether or not to draw this pixel, and handle switches if (rgnCol > 0) { dst++; if (!--rgnCol) rgnCol = rgnBuffer[-1] - rgnBuffer[0], rgnBuffer++; } else { *dst++ = pixel; if (!++rgnCol) rgnCol = rgnBuffer[0] - rgnBuffer[-1], rgnBuffer++; } // calculate the new errors red = (red & 0x07) - (red >> 5); green = (green & 0x07) - (green >> 5); blue = (blue & 0x07) - (blue >> 5); // calculate 2 * the new error for fast ops ahead red2 = red << 1; green2 = green << 1; blue2 = blue << 1; // store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor oBuffer[1].red = red; oBuffer[1].green = green; oBuffer[1].blue = blue; oBuffer[-1].red += (red += red2); oBuffer[-1].green += (green += green2); oBuffer[-1].blue += (blue += blue2); oBuffer->red += (red += red2); oBuffer->green += (green += green2); oBuffer->blue += (blue += blue2); red += red2; green += green2; blue += blue2; oBuffer++; // end of loop: go until done } \ No newline at end of file diff --git a/Source/C/DitherCopyTo16Odd.c b/Source/C/DitherCopyTo16Odd.c new file mode 100644 index 0000000..fae8f59 --- /dev/null +++ b/Source/C/DitherCopyTo16Odd.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void DitherCopyTo16Odd(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, // DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, // short *rgnBuffer, uchar *errorMap, short columns) #if applec #pragma unused(iTable, cTable) #endif // internals: ulong *src = srcRow; // pointer to the 32-bit source row ushort *dst = (ushort *)dstRowStart; // pointer to the 16-bit destination row ulong pixel; // scratch for the current pixel long red; // red scratch area long green; // green scratch area long blue; // blue scratch area long red2; // 2 * the red error; used for fast calculations long green2; // 2 * the green error long blue2; // 2 * the blue error long rgnCol; // region column counter // skip to the ends of everything here dst += columns; src += columns; eBuffer += columns; oBuffer += columns; // initialize our counters and clear out next row red = green = blue = 0; eBuffer[-1].red = eBuffer[-1].green = eBuffer[-1].blue = 0; // set up the region column counter while (*rgnBuffer++ < columns); --rgnBuffer; if (*rgnBuffer == columns) rgnCol = *--rgnBuffer - columns; else rgnCol = columns - *--rgnBuffer; // begin main loop here while (columns--) { // combine the accumulated errors and round to a pixel value --oBuffer; red += oBuffer->red + 8; red >>= 4; red = errorMap[red]; green += oBuffer->green + 8; green >>= 4; green = errorMap[green]; blue += oBuffer->blue + 8; blue >>= 4; blue = errorMap[blue]; // offset the current pixel by the errors pixel = *--src; blue += pixel & 0xff; pixel >>= 8; green += pixel & 0xff; pixel >>= 8; red += pixel & 0xff; // check for overflows and handle them if (red > 255) red = 255; else if (red < 0) red = 0; if (blue > 255) blue = 255; else if (blue < 0) blue = 0; if (green > 255) green = 255; else if (green < 0) green = 0; // assemble the colors into a 16-bit color pixel pixel = red >> 3; pixel <<= 5; pixel += green >> 3; pixel <<= 5; pixel += blue >> 3; // determine whether or not to draw this pixel, and handle switches if (rgnCol > 0) { --dst; if (!--rgnCol) rgnCol = rgnBuffer[-1] - rgnBuffer[0], rgnBuffer--; } else { *--dst = pixel; if (!++rgnCol) rgnCol = rgnBuffer[0] - rgnBuffer[-1], rgnBuffer--; } // Calculate the new errors red = (red & 0x07) - (red >> 5); green = (green & 0x07) - (green >> 5); blue = (blue & 0x07) - (blue >> 5); // Calculate 2 * the new error for fast ops ahead red2 = red << 1; green2 = green << 1; blue2 = blue << 1; // Store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor --eBuffer; eBuffer[-1].red = red; eBuffer[-1].green = green; eBuffer[-1].blue = blue; eBuffer[1].red += (red += red2); eBuffer[1].green += (green += green2); eBuffer[1].blue += (blue += blue2); eBuffer->red += (red += red2); eBuffer->green += (green += green2); eBuffer->blue += (blue += blue2); red += red2; green += green2; blue += blue2; } \ No newline at end of file diff --git a/Source/C/DitherCopyTo8Even.c b/Source/C/DitherCopyTo8Even.c new file mode 100644 index 0000000..19672ba --- /dev/null +++ b/Source/C/DitherCopyTo8Even.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void DitherCopyTo8Even(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, // DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, // short *rgnBuffer, uchar *errorMap, short columns) // internals: ulong *src = srcRow; // pointer to the 32-bit source row uchar *dst = (uchar *)dstRowStart; // pointer to the 8-bit destination row ulong pixel; // scratch for the current pixel long red; // red scratch area long green; // green scratch area long blue; // blue scratch area long red2; // 2 * the red error; used for fast calculations long green2; // 2 * the green error long blue2; // 2 * the blue error long rgnCol; // region column counter // initialize our counters and clear out next row red = green = blue = 0; oBuffer->red = oBuffer->green = oBuffer->blue = 0; // set up the region column counter if (!(rgnCol = *rgnBuffer++)) rgnCol -= *rgnBuffer++; // begin main loop here while (columns--) { // combine the accumulated errors and round to a pixel value red += eBuffer->red + 8; red >>= 4; red = errorMap[red]; green += eBuffer->green + 8; green >>= 4; green = errorMap[green]; blue += eBuffer->blue + 8; blue >>= 4; blue = errorMap[blue]; eBuffer++; // offset the current pixel by the errors pixel = *src++; blue += pixel & 0xff; pixel >>= 8; green += pixel & 0xff; pixel >>= 8; red += pixel & 0xff; // check for overflows and handle them if (red > 255) red = 255; else if (red < 0) red = 0; if (blue > 255) blue = 255; else if (blue < 0) blue = 0; if (green > 255) green = 255; else if (green < 0) green = 0; // get the inverse color table entry pixel = red >> 3; pixel <<= 5; pixel += green >> 3; pixel <<= 5; pixel += blue >> 3; pixel = iTable[pixel]; // determine whether or not to draw this pixel, and handle switches if (rgnCol > 0) { dst++; if (!--rgnCol) rgnCol = rgnBuffer[-1] - rgnBuffer[0], rgnBuffer++; } else { *dst++ = pixel; if (!++rgnCol) rgnCol = rgnBuffer[0] - rgnBuffer[-1], rgnBuffer++; } // calculate the new errors red -= cTable[pixel].rgb.red >> 8; green -= cTable[pixel].rgb.green >> 8; blue -= cTable[pixel].rgb.blue >> 8; // calculate 2 * the new error for fast ops ahead red2 = red << 1; green2 = green << 1; blue2 = blue << 1; // store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor oBuffer[1].red = red; oBuffer[1].green = green; oBuffer[1].blue = blue; oBuffer[-1].red += (red += red2); oBuffer[-1].green += (green += green2); oBuffer[-1].blue += (blue += blue2); oBuffer->red += (red += red2); oBuffer->green += (green += green2); oBuffer->blue += (blue += blue2); red += red2; green += green2; blue += blue2; oBuffer++; // end of loop: go until done } \ No newline at end of file diff --git a/Source/C/DitherCopyTo8Odd.c b/Source/C/DitherCopyTo8Odd.c new file mode 100644 index 0000000..f1c9e75 --- /dev/null +++ b/Source/C/DitherCopyTo8Odd.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void DitherCopyTo8Odd(ulong *srcRow, void *dstRowStart, uchar *iTable, ColorSpec *cTable, // DitherErrorsPtr eBuffer, DitherErrorsPtr oBuffer, // short *rgnBuffer, uchar *errorMap, short columns) // internals: ulong *src = srcRow; // pointer to the 32-bit source row uchar *dst = (uchar *)dstRowStart; ulong pixel; // scratch for the current pixel long red; // red scratch area long green; // green scratch area long blue; // blue scratch area long red2; // 2 * the red error; used for fast calculations long green2; // 2 * the green error long blue2; // 2 * the blue error long rgnCol; // region column counter // Skip to the ends of everything here dst += columns; src += columns; eBuffer += columns; oBuffer += columns; // initialize our counters and clear out next row red = green = blue = 0; eBuffer[-1].red = eBuffer[-1].green = eBuffer[-1].blue = 0; // set up the region column counter while (*rgnBuffer++ < columns); --rgnBuffer; if (*rgnBuffer == columns) rgnCol = *--rgnBuffer - columns; else rgnCol = columns - *--rgnBuffer; // begin main loop here while (columns--) { // combine the accumulated errors and round to a pixel value --oBuffer; red += oBuffer->red + 8; red >>= 4; red = errorMap[red]; green += oBuffer->green + 8; green >>= 4; green = errorMap[green]; blue += oBuffer->blue + 8; blue >>= 4; blue = errorMap[blue]; // offset the current pixel by the errors pixel = *--src; blue += pixel & 0xff; pixel >>= 8; green += pixel & 0xff; pixel >>= 8; red += pixel & 0xff; // check for overflows and handle them if (red > 255) red = 255; else if (red < 0) red = 0; if (blue > 255) blue = 255; else if (blue < 0) blue = 0; if (green > 255) green = 255; else if (green < 0) green = 0; // get the inverse color table entry pixel = red >> 3; pixel <<= 5; pixel += green >> 3; pixel <<= 5; pixel += blue >> 3; pixel = iTable[pixel]; // determine whether or not to draw this pixel, and handle switches if (rgnCol > 0) { --dst; if (!--rgnCol) rgnCol = rgnBuffer[-1] - rgnBuffer[0], rgnBuffer--; } else { *--dst = pixel; if (!++rgnCol) rgnCol = rgnBuffer[0] - rgnBuffer[-1], rgnBuffer--; } // calculate the new errors red -= cTable[pixel].rgb.red >> 8; green -= cTable[pixel].rgb.green >> 8; blue -= cTable[pixel].rgb.blue >> 8; // calculate 2 * the new error for fast ops ahead red2 = red << 1; green2 = green << 1; blue2 = blue << 1; // store 1/16, 3/16, and 5/16 into next row; leave 7/16 for neighbor --eBuffer; eBuffer[-1].red = red; eBuffer[-1].green = green; eBuffer[-1].blue = blue; eBuffer[1].red += (red += red2); eBuffer[1].green += (green += green2); eBuffer[1].blue += (blue += blue2); eBuffer->red += (red += red2); eBuffer->green += (green += green2); eBuffer->blue += (blue += blue2); red += red2; green += green2; blue += blue2; } \ No newline at end of file diff --git a/Source/C/EditMenu.c b/Source/C/EditMenu.c new file mode 100644 index 0000000..cb41c9a --- /dev/null +++ b/Source/C/EditMenu.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * HandleEditChoice(theItem) * * Purpose: Accepts menu events from the Edit menu * Inputs: theItem = the menu item number * Returns: nothing * */ void HandleEditChoice(short theItem) { ImageHandle theImage = FrontImage(), newImage; Rect newRect, theRect; switch (theItem) { case editCutItem: if (IsDialogWindow(FWFrontWindow())) DlgCut(FWFrontWindow()); break; case editCopyItem: if (IsDialogWindow(FWFrontWindow())) DlgCopy(FWFrontWindow()); else if (theImage) SendCopy(); break; case editPasteItem: if (IsDialogWindow(FWFrontWindow())) DlgPaste(FWFrontWindow()); break; case editClearItem: if (IsDialogWindow(FWFrontWindow())) DlgDelete(FWFrontWindow()); break; case editSelectScreenItem: DoSelectScreen(theImage); break; case editCropItem: if (!theImage || !AntsHaveSelection((*theImage)->ants)) break; SelRectToCropRect(theImage, &newRect); if (SendCloneDocument(theImage, &newImage) == noErr) { (*newImage)->flags &= ~(ifSelected + ifScreenSize + ifSelVisible); (*newImage)->flags |= ifCropped; if (SendSetImageBounds((*newImage)->window, &newRect) == noErr) { if (!Full(newImage)) { theRect = (*newImage)->wrect; GlobalRect(&theRect, (*newImage)->window); PositionWindow(&theRect, (*newImage)->dmon); SendSetWindowBounds((*newImage)->window, &theRect); } SendMoveToFront((*newImage)->window); SendSetWindowVis((*newImage)->window, true); } else DoCloseWindow((*newImage)->window, gThePrefs.restoreColors); } break; case editUncropItem: if (!Cropped(theImage)) break; theRect = (*theImage)->grect; /* if ((*theImage)->format->inType == kPICTType && (*theImage)->compression && (Width(&theRect) < (*theImage)->desc.width || Height(&theRect) < (*theImage)->desc.height)) MySetRect(&theRect, 0, 0, (*theImage)->desc.width, (*theImage)->desc.height);*/ SendSetImageBounds((*theImage)->window, &theRect); (*theImage)->flags &= ~(ifSelected + ifScreenSize + ifCropped); break; } } /* * DoSelectScreen(theImage) * * Purpose: Calculates the scaled size of the screen and selects the center of the * active image at that size * Inputs: none * Returns: nothing * */ void DoSelectScreen(ImageHandle theImage) { Rect srect, crect, trect; Boolean itDoesntFit; if (!theImage) return; crect = (*theImage)->crect; GetActiveRect((*theImage)->dmon, &srect); if (!Full(theImage)) srect.top += gTitleBarHeight; OffsetRect(&srect, -srect.left, -srect.top); if (srect.right >= Width(&crect)) srect.right = Width(&crect); if (srect.bottom >= Height(&crect)) srect.bottom = Height(&crect); do { itDoesntFit = false; trect = srect; MapRect(&trect, &crect, &(*theImage)->wrect); MapRect(&trect, &(*theImage)->wrect, &crect); if (Width(&trect) > Width(&srect)) { srect.right--; itDoesntFit = true; } if (Height(&trect) > Height(&srect)) { srect.bottom--; itDoesntFit = true; } } while (itDoesntFit); OffsetRect(&srect, crect.left + ((Width(&crect) - srect.right) >> 1), crect.top + ((Height(&crect) - srect.bottom) >> 1)); MapRect(&srect, &crect, &(*theImage)->wrect); (*theImage)->flags |= ifScreenSize; SendSetSelection(theImage, &srect); } extern void SelRectToCropRect(ImageHandle theImage, Rect *newRect) { GetAntsSelection((*theImage)->ants, newRect); MapRect(newRect, &(*theImage)->wrect, &(*theImage)->crect); if (ScreenSize(theImage)) ForceScreenSize(theImage, newRect); } \ No newline at end of file diff --git a/Source/C/EventHandlers.c b/Source/C/EventHandlers.c new file mode 100644 index 0000000..8027672 --- /dev/null +++ b/Source/C/EventHandlers.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "EventHandlers.h" //===================================================================================== // Global variables local to this module //===================================================================================== static Boolean gDrawMenuBar = true; static long gLastEventWhen = 0L; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static void UpdateFastImages(void); static void UpdateNextSlowImage(void); static void UnhideWindows(void); //===================================================================================== // void MainEventLoop(void) //===================================================================================== // Serves as the main event loop for the application. //===================================================================================== extern void MainEventLoop(void) { Boolean isNullEvent, isDialogEvent; MonitorHandle theMonitor; EventRecord theEvent; RgnHandle mouseRgn; if (!(mouseRgn = NewRgn())) FatalError(errNoMemory); while (!gDone) { // ensure we are pointing to a valid *onscreen* port MySetPort((CGrafPtr)FWFrontWindow()); UpdateCursor(mouseRgn); // verify our monitor configuration, and update affected images while (theMonitor = MonitorChanged()) UpdateImages(theMonitor); // identify the next event and dispatch it appropriately isNullEvent = !WaitNextEvent(everyEvent, &theEvent, kSleepTime, mouseRgn); isDialogEvent = FWIsDialogEvent(&theEvent); UpdateCursor(mouseRgn); if (isNullEvent) { DialogPtr theDialog; short itemHit; theDialog = FWFrontWindow(); if (theDialog && WindowKind(theDialog) == dialogKind) FWDialogSelect(&theEvent, &theDialog, &itemHit); HandleNullEvent(); } else DispatchMainEvent(&theEvent, isDialogEvent); // handle any selections from the menu that pertain to the slide show if (gSlideShow && gPendingButton != -1) { if ((*gSlideOptions)->userControl) gSlideShow = HandleUserControlButton(gPendingButton); else gSlideShow = HandleAutomaticButton(gPendingButton); if (!gSlideShow) CleanUpSlideShow(); } // if we're in screen saver mode and the slide show ended, quit now if (gScreenSaver) { if (!gSlideShow) gDone = true; else EnsureFrontmost(); } // if we've invalidated the menu bar, redraw it now if (gDrawMenuBar) { AdjustMenus(); if (gMenuVisible) DrawMenuBar(); gDrawMenuBar = false; } } } //===================================================================================== // void MyInvalMenuBar(void) //===================================================================================== // Invalidate the menu bar area, so we draw it before taking the next event. //===================================================================================== extern void MyInvalMenuBar(void) { gDrawMenuBar = true; } //===================================================================================== // void DispatchMainEvent(EventRecord *theEvent, Boolean isDialogEvent) //===================================================================================== // Dispatches events from the main event loop. //===================================================================================== extern void DispatchMainEvent(EventRecord *theEvent, Boolean isDialogEvent) { switch (theEvent->what) { case mouseDown: // if we're in screen saver mode, always abort if (gSlideShow && gScreenSaver) SendQuitApplication(); else if (isDialogEvent) HandleMouseDownDialog(theEvent); else HandleMouseDownEvent(theEvent); break; case keyDown: if (theEvent->message == kCreator) break; case autoKey: if (gSlideShow && gScreenSaver) SendQuitApplication(); else if (isDialogEvent) HandleKeyDownDialog(theEvent); else HandleKeyDownEvent(theEvent); break; case activateEvt: if (isDialogEvent) HandleActivateDialog(theEvent); else HandleActivateEvent(theEvent); break; case updateEvt: if (isDialogEvent) HandleUpdateDialog(theEvent); else HandleUpdateEvent(theEvent); break; case osEvt: HandleOSEvent(theEvent); break; case diskEvt: HandleDiskEvent(theEvent); break; case kHighLevelEvent: AEProcessAppleEvent(theEvent); break; } } //===================================================================================== // void HandleNullEvent(void) //===================================================================================== // Handles null events. //===================================================================================== extern void HandleNullEvent(void) { static long gOldCount = 0L; ImageHandle theImage = FrontImage(); long newCount = TickCount(); Point point = { 0, 0 }; // if balloon help is on, say the magic words for the appropriate window if (HMGetBalloons()) DispatchBalloonHelp(); // scroll the credits IdleCredits(); // if the frontmost image has a selection, animate it if (!gSlideShow && !gInBackground && theImage) { if ((newCount - gOldCount) >= (kSelRectSpeed / 2)) { gOldCount = newCount; AnimateAnts((*theImage)->ants); } } // if there's a slide show going on, update the slide show timers if (gSlideShow == kRunning) { HandleSlideNullEvent(); if (gDone) return; } // update any pending windows that have associated gworlds UpdateFastImages(); // if there's been sufficient delay, update the next pending window if ((newCount - gLastEventWhen) > kUpdateDelay && (!gInBackground || gThePrefs.updateBack)) UpdateNextSlowImage(); } //===================================================================================== // void EnsureFrontmost(void) //===================================================================================== // Ensure that we are the frontmost application. //===================================================================================== extern void EnsureFrontmost(void) { ProcessSerialNumber currentProcess, frontProcess; ProcessInfoRec theInfo; theInfo.processInfoLength = sizeof(ProcessInfoRec); theInfo.processName = nil; theInfo.processAppSpec = nil; GetFrontProcess(&frontProcess); GetProcessInformation(&frontProcess, &theInfo); if (theInfo.processSignature != kDarksideCreator && theInfo.processSignature != kCreator) { GetCurrentProcess(¤tProcess); SetFrontProcess(¤tProcess); } } //===================================================================================== // void DispatchBalloonHelp(void) //===================================================================================== // Determines whether we should pop up some balloons, and calls the appropriate handler // routine. //===================================================================================== extern void DispatchBalloonHelp(void) { Point mouseLoc = GlobalMouse(); WindowPtr theWindow; long refCon; short part; part = FindWindow(mouseLoc, &theWindow); refCon = GetWRefCon(theWindow); if ((part == inContent || part == inGrow) && WindowHilited(theWindow)) { switch (refCon) { case kCommentsWindowID: DoCommentsHelp(mouseLoc); break; case kColorsWindowID: DoColorsHelp(mouseLoc); break; case kStatWindowID: DoStatsHelp(mouseLoc); break; case kSlideControlsWindowID: DoSlideControlsHelp(mouseLoc); break; case kImageWindowID: if (theWindow != GetSlideBackWindow()) DoImageHelp(theWindow, mouseLoc); break; case kHelpWindowID: DoHelpHelp(mouseLoc); break; } } } //===================================================================================== // void UpdateFastImages(void) //===================================================================================== // Traverses the window list in search of images that can be updated quickly. //===================================================================================== static void UpdateFastImages(void) { WindowPtr theWindow, frontWindow = FWFrontWindow(); ImageHandle theImage; for (theWindow = frontWindow; theWindow; theWindow = NextWindow(theWindow)) { if ((theImage = FindImage(theWindow)) && !EmptyRgn((*theImage)->update)) { if (theWindow == frontWindow && !gInBackground && !Aborted(theImage)) UpdateImage(theImage); else if ((*theImage)->gworld && EqualSizeRect(&(*theImage)->gworld->portRect, &(*theImage)->wrect)) UpdateImage(theImage); } } } //===================================================================================== // void UpdateNextSlowImage(void) //===================================================================================== // Traverses the window list in search of the next window to be updated. //===================================================================================== static void UpdateNextSlowImage(void) { WindowPtr theWindow = FWFrontWindow(); ImageHandle theImage; if (theWindow) { short var = GetWVariant(theWindow); if (var == movableDBoxProc || (var >= dBoxProc && var <= altDBoxProc)) return; } for ( ; theWindow; theWindow = NextWindow(theWindow)) { if ((theImage = FindImage(theWindow)) && !Aborted(theImage) && !EmptyRgn((*theImage)->update)) { UpdateImage(theImage); gLastEventWhen = TickCount() - (kUpdateDelay >> 1); break; } } } //===================================================================================== // void HandleMouseDownDialog(EventRecord *theEvent) //===================================================================================== // Handles mouse down events in dialog windows. //===================================================================================== extern void HandleMouseDownDialog(EventRecord *theEvent) { Boolean isCmdKey = (theEvent->modifiers & cmdKey) != 0; DialogPtr theDialog, frontDialog = FWFrontWindow(); short itemHit, thePart, var; Boolean modalDialog; thePart = FindWindow(theEvent->where, &theDialog); var = GetWVariant(theDialog); modalDialog = (var >= dBoxProc && var <= altDBoxProc) || var == movableDBoxProc; switch (thePart) { case inMenuBar: HandleMenuClick(theEvent); break; case inSysWindow: SystemClick(theEvent, theDialog); break; case inContent: if (theDialog != frontDialog) SendMoveToFront(theDialog); else if (FWDialogSelect(theEvent, &theDialog, &itemHit)) DispatchDialogEvent(theDialog, itemHit); break; case inDrag: if (modalDialog && theDialog != frontDialog && !isCmdKey) SysBeep(30); else HandleDragClick(theEvent, theDialog); break; case inGoAway: if (modalDialog && theDialog != frontDialog) SysBeep(30); else HandleCloseClick(theEvent, theDialog); break; case inGrow: if (modalDialog && theDialog != frontDialog) SysBeep(30); else HandleGrowClick(theEvent, theDialog); break; case inZoomIn: case inZoomOut: if (modalDialog && theDialog != frontDialog) SysBeep(30); else HandleZoomClick(theEvent, thePart, theDialog); break; } gLastEventWhen = TickCount(); } //===================================================================================== // void HandleMouseDownEvent(EventRecord *theEvent) //===================================================================================== // Handles mouse down events in non-dialog windows. //===================================================================================== extern void HandleMouseDownEvent(EventRecord *theEvent) { WindowPtr theWindow; short thePart; thePart = FindWindow(theEvent->where, &theWindow); if (WindowKind(theWindow) == dialogKind) HandleMouseDownDialog(theEvent); // if it's a mouse down during a slide show (but not in a floating window) // then toggle the visibility of the slide show controls else if (gSlideShow == kRunning && WindowKind(theWindow) != floatingWindowKind && (thePart == inContent || thePart == inGrow)) { theWindow = GetSlideControlsWindow(); if (!theWindow) { if (OpenSlideControls() == noErr) ChangeActive(GetSlideControlsWindow()); } else CloseSlideControls(); // otherwise, dispatch to the appropriate mouse down handler } else { switch (thePart) { case inMenuBar: HandleMenuClick(theEvent); break; case inSysWindow: SystemClick(theEvent, theWindow); break; case inContent: HandleContentClick(theEvent, theWindow); break; case inDrag: HandleDragClick(theEvent, theWindow); break; case inGoAway: HandleCloseClick(theEvent, theWindow); break; case inGrow: HandleGrowClick(theEvent, theWindow); break; case inZoomIn: case inZoomOut: HandleZoomClick(theEvent, thePart, theWindow); break; } } gLastEventWhen = TickCount(); } //===================================================================================== // void HandleMenuClick(EventRecord *theEvent) //===================================================================================== // Handles mouse downs in the menu bar. //===================================================================================== extern void HandleMenuClick(EventRecord *theEvent) { AdjustMenus(); HandleMenuChoice(MenuSelect(theEvent->where)); AdjustMenus(); } //===================================================================================== // void HandleContentClick(EventRecord *theEvent, WindowPtr theWindow) //===================================================================================== // Handles mouse downs in the content region of a window. //===================================================================================== extern void HandleContentClick(EventRecord *theEvent, WindowPtr theWindow) { WindowPtr frontWindow = FWFrontWindow(); short var = GetWVariant(frontWindow); OSType id = GetWRefCon(theWindow); ImageHandle theImage; if ((var == dBoxProc || var == movableDBoxProc) && theWindow != frontWindow) SysBeep(30); else if (id == kSlideControlsWindowID) { if (theWindow != frontWindow) SendMoveToFront(theWindow); HandleSlideControlsClick(theEvent->where, theEvent->modifiers, true); } else if (theImage = FindImage(theWindow)) HandleImageClick(theImage, theEvent); else if (theWindow == GetCommentsWindow()) HandleCommentsClick(theEvent); else if (theWindow == GetStatWindow()) HandleStatClick(theEvent); else if (theWindow != frontWindow && theWindow != FrontWindow()) SendMoveToFront(theWindow); else if (id == kHelpWindowID) HandleHelpClick(theEvent->where); } //===================================================================================== // void HandleDragClick(EventRecord *theEvent, WindowPtr theWindow) //===================================================================================== // Handles mouse downs in the drag region of a window. //===================================================================================== extern void HandleDragClick(EventRecord *theEvent, WindowPtr theWindow) { Boolean isCmdKey = (theEvent->modifiers & cmdKey) != 0; WindowPtr frontWindow = FWFrontWindow(); Rect theRect = (*GetGrayRgn())->rgnBBox; short var = GetWVariant(frontWindow); if ((var == dBoxProc || var == movableDBoxProc) && theWindow != frontWindow && !isCmdKey) SysBeep(30); else { if (theWindow != frontWindow && theWindow != FrontWindow() && !isCmdKey) SendMoveToFront(theWindow); FWDragWindow(theWindow, theEvent->where, &theRect); theRect = theWindow->portRect; GlobalRect(&theRect, theWindow); SendSetWindowBounds(theWindow, &theRect); } } //===================================================================================== // void HandleCloseClick(EventRecord *theEvent, WindowPtr theWindow) //===================================================================================== // Handles mouse downs in the close box of a window. //===================================================================================== extern void HandleCloseClick(EventRecord *theEvent, WindowPtr theWindow) { WindowPtr nextWindow; short firstKind; if (TrackGoAway(theWindow, theEvent->where)) { if (theEvent->modifiers & optionKey) { firstKind = WindowKind(theWindow); for (theWindow = GetFirstWindow(); theWindow; theWindow = nextWindow) { nextWindow = NextWindow(theWindow); if (theWindow == GetSlideControlsWindow()) continue; if ((firstKind == floatingWindowKind && WindowKind(theWindow) == floatingWindowKind) || (firstKind != floatingWindowKind && WindowKind(theWindow) != floatingWindowKind)) SendCloseWindow(theWindow); } } else SendCloseWindow(theWindow); } } //===================================================================================== // void HandleGrowClick(EventRecord *theEvent, WindowPtr theWindow) //===================================================================================== // Handles mouse downs in the grow region of a window. //===================================================================================== extern void HandleGrowClick(EventRecord *theEvent, WindowPtr theWindow) { WindowPtr frontWindow = FWFrontWindow(); short var = GetWVariant(frontWindow); if ((var == dBoxProc || var == movableDBoxProc) && theWindow != frontWindow) SysBeep(30); else if (GetWRefCon(theWindow) == kSlideControlsWindowID) HandleContentClick(theEvent, theWindow); else if (theWindow != frontWindow && theWindow != FrontWindow()) SendMoveToFront(theWindow); else if (GetWRefCon(theWindow) == kHelpWindowID) HandleHelpGrow(theEvent->where); } //===================================================================================== // void HandleZoomClick(EventRecord *theEvent, short thePart, WindowPtr theWindow) //===================================================================================== // Handles mouse downs in the zoom box of a window. //===================================================================================== extern void HandleZoomClick(EventRecord *theEvent, short thePart, WindowPtr theWindow) { if (TrackBox(theWindow, theEvent->where, thePart)) SendSetZoomed(theWindow, !IsZoomed(theWindow)); } //===================================================================================== // void HandleKeyDownDialog(EventRecord *theEvent) //===================================================================================== // Handles key down events for a dialog. //===================================================================================== extern void HandleKeyDownDialog(EventRecord *theEvent) { Boolean isCmdKey = (theEvent->modifiers & cmdKey) != 0, isCancelKey, isOKKey, isHelpKey; uchar theChar = theEvent->message & charCodeMask; DialogPtr theDialog = FWFrontWindow(); OSType dialogID = GetWRefCon(theDialog); short itemHit = 0; isCancelKey = (theChar == kEscapeChar) || (isCmdKey && theChar == '.'); isHelpKey = (theChar == kHelpChar) || (isCmdKey && (theChar == '/' || theChar == '?')); isOKKey = (theChar == kReturnChar || theChar == kEnterChar); // if the help key was hit, select the appropriate menu item if (isHelpKey) { HiliteMenu(kHMHelpMenuID); HandleMenuChoice(MakeMenuSelection(kHMHelpMenuID, gHelpItem)); // handle the cmd-. and escape combinations } else if (isCancelKey) itemHit = HandleDialogCancelKey(theDialog); // handle return or enter else if (isOKKey) itemHit = HandleDialogOKKey(theDialog); // handle command-key combinations else if (isCmdKey) { if (theChar == '=') HandleMenuChoice(MenuKey('+')); else HandleMenuChoice(PowerMenuKey(theEvent->message, theEvent->modifiers, GetMHandle(rFileMenu))); // handle single-letter buttons } else if ((theChar >= 'A' && theChar <= 'Z') || (theChar >= 'a' && theChar <= 'z')) itemHit = HandleDialogLetterKey(theDialog, theChar); // make a special exception for certain dialogs before further processing else if (dialogID == kSlideShowDialogID) { if (!HandleSlideOptionsKey(theChar)) FWDialogSelect(theEvent, &theDialog, &itemHit); } else if (dialogID == kPrefsDialogID) { if (!HandlePrefsKey(theChar)) FWDialogSelect(theEvent, &theDialog, &itemHit); // otherwise, dispatch to the dialog handler } else FWDialogSelect(theEvent, &theDialog, &itemHit); // if we were passed back an item to hit, hit it if (itemHit) DispatchDialogEvent(theDialog, itemHit); } //===================================================================================== // void HandleKeyDownEvent(EventRecord *theEvent) //===================================================================================== // Handles key down events for a non-dialog window. //===================================================================================== extern void HandleKeyDownEvent(EventRecord *theEvent) { Boolean isCmdKey = (theEvent->modifiers & cmdKey) != 0, isAbortKey, isHelpKey; uchar theChar = theEvent->message & charCodeMask; WindowPtr frontWindow = FWFrontWindow(); // if this should have been a dialog event, treat it as such if (WindowKind(frontWindow) == dialogKind) { HandleKeyDownDialog(theEvent); return; } AdjustMenus(); isAbortKey = (theChar == kEscapeChar) || (isCmdKey && theChar == '.'); isHelpKey = (theChar == kHelpChar) || (isCmdKey && (theChar == '/' || theChar == '?')); // if we're in a slide show, dispatch to the slide show handler if (gSlideShow && !isCmdKey) { HandleSlideControlsKey(theChar, theEvent->modifiers, true); return; } // if the help key was hit, select the appropriate menu item else if (isHelpKey) { HiliteMenu(kHMHelpMenuID); HandleMenuChoice(MakeMenuSelection(kHMHelpMenuID, gHelpItem)); // handle command-key combinations } else if (isCmdKey) { if (theChar == '=') HandleMenuChoice(MenuKey('+')); else HandleMenuChoice(PowerMenuKey(theEvent->message, theEvent->modifiers, GetMHandle(rFileMenu))); // everything else goes to the appropriate window } else if (frontWindow && GetWRefCon(frontWindow) == kHelpWindowID) HandleHelpKey(theChar, (theEvent->message & keyCodeMask) >> 8); AdjustMenus(); gLastEventWhen = TickCount(); } //===================================================================================== // void HandleActivateDialog(EventRecord *theEvent) //===================================================================================== // Handles activate events for a dialog. //===================================================================================== extern void HandleActivateDialog(EventRecord *theEvent) { DialogPtr theDialog = (DialogPtr)theEvent->message; short itemHit; if (GetWRefCon(theDialog) == sfMainDialogRefCon) return; FWDialogSelect(theEvent, &theDialog, &itemHit); } //===================================================================================== // void HandleActivateEvent(EventRecord *theEvent) //===================================================================================== // Handles activate events for a non-dialog window. //===================================================================================== extern void HandleActivateEvent(EventRecord *theEvent) { WindowPtr theWindow = (WindowPtr)theEvent->message; Boolean nowActive = (theEvent->modifiers & 1) != 0; ImageHandle theImage = FindImage(theWindow); if (!theWindow) return; PushPort(); MySetPort((CGrafPtr)theWindow); switch (GetWRefCon(theWindow)) { case kHelpWindowID: HandleHelpActivate(nowActive); break; default: if (theImage) HandleImageActivate(theImage, nowActive); break; } PopPort(); } //===================================================================================== // void HandleUpdateDialog(EventRecord *theEvent) //===================================================================================== // Handles update events for a dialog. //===================================================================================== extern void HandleUpdateDialog(EventRecord *theEvent) { DialogPtr theDialog = (DialogPtr)theEvent->message; OSType dialogID = GetWRefCon(theDialog); if (dialogID == sfMainDialogRefCon) return; PushPort(); MySetPort((CGrafPtr)theDialog); BeginUpdate(theDialog); UpdateDialog(theDialog, theDialog->visRgn); if (dialogID == kSlideShowDialogID) UpdateSlideOptionsButtons(); EndUpdate(theDialog); PopPort(); } //===================================================================================== // void HandleUpdateEvent(EventRecord *theEvent) //===================================================================================== // Handles update events for a non-dialog window. //===================================================================================== extern void HandleUpdateEvent(EventRecord *theEvent) { WindowPtr theWindow = (WindowPtr)theEvent->message; ImageHandle theImage = FindImage(theWindow); OSType refCon = GetWRefCon(theWindow); Boolean defer = true; PushPort(); MySetPort((CGrafPtr)theWindow); if (!theImage) { BeginUpdate(theWindow); if (WindowKind(theWindow) == dialogKind) UpdateDialog(theWindow, theWindow->visRgn); else if (refCon == kHelpWindowID) UpdateHelp(); else if (refCon == kStatWindowID) DrawStatWindow(); else if (refCon == kCommentsWindowID) UpdateCommentsWindow(); else if (refCon == kColorsWindowID) DrawColorsWindow(); else if (refCon == kSlideControlsWindowID) DrawSlideControlsWindow(); else if (theWindow == GetSlideBackWindow()) DrawSlideBackWindow(); EndUpdate(theWindow); } else { Boolean fastGWorld = (*theImage)->gworld && EqualSizeRect(&(*theImage)->gworld->portRect, &(*theImage)->wrect); if (fastGWorld || (theWindow == FWFrontWindow() && !gInBackground)) defer = false; if (defer) DeferImageUpdate(theImage); else { WindowPtr ctlWindow = GetSlideControlsWindow(); short oldSettings[4], i; if (ctlWindow) { for (i = kReverseButton; i <= kForwardButton; i++) { oldSettings[i] = GetSlideControlButton(i); SetSlideControlButton(i, disabled); } DrawSlideControlsWindow(); } UpdateImage(theImage); if (!fastGWorld) gLastEventWhen = TickCount(); if (ctlWindow) { for (i = kReverseButton; i <= kForwardButton; i++) SetSlideControlButton(i, oldSettings[i]); DrawSlideControlsWindow(); } } } PopPort(); } //===================================================================================== // void HandleOSEvent(EventRecord *theEvent) //===================================================================================== // Handles operating system events. //===================================================================================== extern void HandleOSEvent(EventRecord *theEvent) { WindowPtr frontWindow; Boolean resume; short var; switch ((theEvent->message >> 24) & 0xff) { case mouseMovedMessage: break; case suspendResumeMessage: resume = (theEvent->message & resumeFlag) != 0; if (resume) { // resume SetUpDevices(); gInBackground = false; if (gHidden) UnhideWindows(); FWShowFloatingWindows(); frontWindow = FWFrontWindow(); ChangeActive(frontWindow); theEvent->what = activateEvt; theEvent->message = (long)frontWindow; theEvent->modifiers = 1; HandleActivateEvent(theEvent); } else { // suspend frontWindow = FWFrontWindow(); if (frontWindow) var = GetWVariant(frontWindow); if (!frontWindow || var != movableDBoxProc) FWHideFloatingWindows(); theEvent->what = activateEvt; theEvent->message = (long)FWFrontWindow(); theEvent->modifiers = 0; HandleActivateEvent(theEvent); ChangeActive(nil); ResetDevices(); if (!gMenuVisible && !gScreenSaver) UnhideMenuBar(); gInBackground = true; } break; } } //===================================================================================== // void HandleOSEvent(EventRecord *theEvent) //===================================================================================== // Handles operating system events. //===================================================================================== static void UnhideWindows(void) { WindowPtr backWindow = GetSlideBackWindow(), theWindow; ImageHandle theImage, frontImage = FrontImage(); if (frontImage) FWShowWindow((*frontImage)->window); for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if ((*theImage)->window) FWShowWindow((*theImage)->window); if (backWindow) FWShowWindow(backWindow); for (theWindow = GetFirstWindow(); theWindow; theWindow = NextWindow(theWindow)) if (WindowKind(theWindow) != floatingWindowKind && !FindImage(theWindow) && theWindow != backWindow) SendBehind(theWindow, backWindow); gHidden = false; gPendingButton = kForwardButton; } //===================================================================================== // void HandleDiskEvent(EventRecord *theEvent) //===================================================================================== // Handles disk inserted events. //===================================================================================== extern void HandleDiskEvent(EventRecord *theEvent) { if (HiWord(theEvent->message) != noErr) { Point thePoint = { -1, -1 }; DIBadMount(thePoint, theEvent->message); } } //===================================================================================== // void DispatchDialogEvent(DialogPtr theDialog, short theItem) //===================================================================================== // Dispatches a dialog event to the appropriate handler. //===================================================================================== extern void DispatchDialogEvent(DialogPtr theDialog, short theItem) { switch (GetWRefCon(theDialog)) { case kSlideShowDialogID: HandleSlideOptionsEvent(theItem); break; case kPrefsDialogID: HandlePrefsEvent(theItem); break; case kAboutHelpDialogID: HandleAboutHelpEvent(theItem); break; } } \ No newline at end of file diff --git a/Source/C/EventUtils.c b/Source/C/EventUtils.c new file mode 100644 index 0000000..2b3f86a --- /dev/null +++ b/Source/C/EventUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "EventUtils.h" //===================================================================================== // Local variables //===================================================================================== static Pattern gAnimPatternT = { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 }; static Pattern gAnimPatternB = { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 }; static Pattern gAnimPatternL = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; static Pattern gAnimPatternR = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; static Pattern gSelPattern = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }; //===================================================================================== // void UpdateCursor(RgnHandle theRgn) //===================================================================================== // Update the cursor according to where the mouse pointer is. //===================================================================================== extern void UpdateCursor(RgnHandle theRgn) { static RgnHandle gSizeRgn = nil, gHandRgn = nil, gCrossRgn = nil, gArrowRgn = nil; ImageHandle frontImage = FrontImage(); Point theMouse, offset = { 0, 0 }; Rect theRect; if (!gSizeRgn) gSizeRgn = NewRgn(), gHandRgn = NewRgn(), gCrossRgn = NewRgn(), gArrowRgn = NewRgn(); SetEmptyRgn(gSizeRgn); SetEmptyRgn(gHandRgn); SetEmptyRgn(gCrossRgn); SetRectRgn(gArrowRgn, -32767, -32767, 32767, 32767); if (frontImage && !IsAboutBox(frontImage) && !gSlideShow && (!Full(frontImage) || (*frontImage)->dmon != gMainMonitor || !gMenuVisible)) { PushPort(); MySetPort((CGrafPtr)(*frontImage)->window); GetMouse(&theMouse); LocalToGlobal(&theMouse); LocalToGlobal(&offset); PopPort(); theRect = (*frontImage)->wrect; SetRectRgn(gSizeRgn, theRect.right - 16, theRect.bottom - 16, theRect.right, theRect.bottom); SectRgn(gSizeRgn, (*frontImage)->window->visRgn, gSizeRgn); OffsetRgn(gSizeRgn, offset.h, offset.v); RectRgn(gCrossRgn, &theRect); SectRgn(gCrossRgn, (*frontImage)->window->visRgn, gCrossRgn); OffsetRgn(gCrossRgn, offset.h, offset.v); GetAntsSelection((*frontImage)->ants, &theRect); RectRgn(gHandRgn, &theRect); SectRgn(gHandRgn, (*frontImage)->window->visRgn, gHandRgn); OffsetRgn(gHandRgn, offset.h, offset.v); DiffRgn(gArrowRgn, gCrossRgn, gArrowRgn); DiffRgn(gCrossRgn, gHandRgn, gCrossRgn); DiffRgn(gCrossRgn, gSizeRgn, gCrossRgn); DiffRgn(gHandRgn, gSizeRgn, gHandRgn); } if (PtInRgn(theMouse, gArrowRgn)) StopSpinning(&qd.arrow), CopyRgn(gArrowRgn, theRgn); if (PtInRgn(theMouse, gCrossRgn)) StopSpinning(*gCross), CopyRgn(gCrossRgn, theRgn); if (PtInRgn(theMouse, gHandRgn)) StopSpinning(*gHand), CopyRgn(gHandRgn, theRgn); if (PtInRgn(theMouse, gSizeRgn)) StopSpinning(*gSize), CopyRgn(gSizeRgn, theRgn); } //===================================================================================== // Boolean TrackDragRect(Point theAnchor, ImageHandle theImage) //===================================================================================== // Tracks the mouse while the user drags an existing selection rectangle. //===================================================================================== extern Boolean TrackDragRect(Point theAnchor, ImageHandle theImage) { Boolean result, inRect, drew = true; Rect newRect, theRect, oldRect; Point lastPoint, newPoint; PenState oldState; short offset; GetAntsSelection((*theImage)->ants, &oldRect); newRect = oldRect; PushPort(); MySetPort((CGrafPtr)(*theImage)->window); theRect = (*theImage)->wrect; ClipRect(&theRect); GetPenState(&oldState); PenNormal(); PenMode(srcXor); PenPat(&gSelPattern); lastPoint = theAnchor; SubPt(TopLeft(newRect), &theAnchor); FrameRect(&newRect); while (StillDown()) { GetMouse(&newPoint); if (newPoint.h == lastPoint.h && newPoint.v == lastPoint.v) continue; lastPoint = newPoint; if (drew) FrameRect(&newRect); inRect = PtInRect(newPoint, &theRect); if (!inRect && gDragMgrPresent) { PopPort(); return true; } GetAntsSelection((*theImage)->ants, &newRect); SubPt(theAnchor, &newPoint); OffsetRect(&newRect, newPoint.h - oldRect.left, newPoint.v - oldRect.top); if ((offset = theRect.left - newRect.left) > 0) { OffsetRect(&newRect, offset, 0); if (inRect) theAnchor.h -= offset; } if ((offset = theRect.right - newRect.right) < 0) { OffsetRect(&newRect, offset, 0); if (inRect) theAnchor.h -= offset; } if ((offset = theRect.top - newRect.top) > 0) { OffsetRect(&newRect, 0, offset); if (inRect) theAnchor.v -= offset; } if ((offset = theRect.bottom - newRect.bottom) < 0) { OffsetRect(&newRect, 0, offset); if (inRect) theAnchor.v -= offset; } if (drew = inRect) FrameRect(&newRect); } if (drew) FrameRect(&newRect); result = PtInRect(lastPoint, &theRect); if (result) SetAntsSelection((*theImage)->ants, &newRect); SetPenState(&oldState); PopPort(); return false; } //===================================================================================== // Boolean TrackGrowWindow(Point thePoint, ImageHandle theImage, Boolean constrain, // Rect *newRect) //===================================================================================== // Tracks the mouse while the user drags the grow region of a window; could probably // use some cleaning up. //===================================================================================== extern Boolean TrackGrowWindow(Point thePoint, ImageHandle theImage, Boolean constrain, Rect *newRect) { Rect drawRect, theRect, dragBounds, oldRect, rect1; short offsetH, offsetV, tempH, tempV; Point newPoint, lastPoint, realLast; GrafPort tempPort; PenState oldState; StopSpinning(*gSize); if (Full(theImage)) { drawRect = theRect = oldRect = (*theImage)->wrect; dragBounds = (*theImage)->window->portRect; InsetRect(&drawRect, -1, -1); } else { drawRect = (*GetStrucRgn((*theImage)->window))->rgnBBox; theRect = (*theImage)->window->portRect; GlobalRect(&theRect, (*theImage)->window); oldRect = theRect; dragBounds = (*GetGrayRgn())->rgnBBox; } PushPort(); MySetPort((CGrafPtr)(*theImage)->window); LocalToGlobal(&thePoint); realLast = lastPoint = thePoint; OpenPort(&tempPort); CopyRgn(GetGrayRgn(), tempPort.visRgn); MySetPort((CGrafPtr)&tempPort); GetPenState(&oldState); PenNormal(); PenMode(srcXor); PenPat(&gSelPattern); FrameRect(&drawRect); while (StillDown()) { newPoint = GlobalMouse(); if ((newPoint.h == realLast.h) && (newPoint.v == realLast.v)) continue; FrameRect(&drawRect); offsetH = newPoint.h - lastPoint.h; offsetV = newPoint.v - lastPoint.v; theRect.right += offsetH; theRect.bottom += offsetV; lastPoint = newPoint; if (constrain) { if (abs(newPoint.v - drawRect.bottom) > abs(newPoint.h - drawRect.right)) { rect1 = theRect; rect1.bottom = rect1.top + ((long)Height(&oldRect) * (long)Width(&rect1)) / (long)Width(&oldRect); } else { rect1 = theRect; rect1.right = rect1.left + ((long)Width(&oldRect) * (long)Height(&rect1)) / (long)Height(&oldRect); } drawRect.right += offsetH; drawRect.bottom += offsetV; offsetH = rect1.right - theRect.right; offsetV = rect1.bottom - theRect.bottom; theRect = rect1; } else { drawRect.right += offsetH; drawRect.bottom += offsetV; offsetH = offsetV = 0; } if (theRect.bottom < (theRect.top + 32)) { offsetV += (theRect.top + 32) - theRect.bottom; theRect.bottom = theRect.top + 32; if (constrain) { tempH = theRect.left + ((long)Width(&oldRect) * (long)Height(&theRect)) / (long)Height(&oldRect); offsetH += tempH - theRect.right; theRect.right = tempH; } } else if (theRect.bottom > dragBounds.bottom) { offsetV += dragBounds.bottom - theRect.bottom; theRect.bottom = dragBounds.bottom; if (constrain) { tempH = theRect.left + ((long)Width(&oldRect) * (long)Height(&theRect)) / (long)Height(&oldRect); offsetH += tempH - theRect.right; theRect.right = tempH; } } if (theRect.right < (theRect.left + 32)) { offsetH += (theRect.left + 32) - theRect.right; theRect.right = theRect.left + 32; if (constrain) { tempV = theRect.top + ((long)Height(&oldRect) * (long)Width(&theRect)) / (long)Width(&oldRect); offsetV += tempV - theRect.bottom; theRect.bottom = tempV; } } else if (theRect.right > dragBounds.right) { offsetH += dragBounds.right - theRect.right; theRect.right = dragBounds.right; if (constrain) { tempV = theRect.top + ((long)Height(&oldRect) * (long)Width(&theRect)) / (long)Width(&oldRect); offsetV += tempV - theRect.bottom; theRect.bottom = tempV; } } drawRect.right += offsetH; drawRect.bottom += offsetV; lastPoint.h += offsetH; lastPoint.v += offsetV; if (Full(theImage)) { offsetH = ((Width(&dragBounds) - Width(&theRect)) >> 1) - theRect.left; offsetV = ((Height(&dragBounds) - Height(&theRect)) >> 1) - theRect.top; lastPoint.h += offsetH; lastPoint.v += offsetV; OffsetRect(&drawRect, offsetH, offsetV); OffsetRect(&theRect, offsetH, offsetV); } FrameRect(&drawRect); realLast = newPoint; } FrameRect(&drawRect); *newRect = theRect; SetPenState(&oldState); PopPort(); ClosePort(&tempPort); return (Width(&theRect) != Width(&oldRect)) || (Height(&theRect) != Height(&oldRect)); } \ No newline at end of file diff --git a/Source/C/FileMenu.c b/Source/C/FileMenu.c new file mode 100644 index 0000000..eed638b --- /dev/null +++ b/Source/C/FileMenu.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "FileMenu.h" //=================================================================================== // OpenData: Contains options information that is set from within the Open dialog. //=================================================================================== typedef struct { Boolean showAll; short lastVRef; long lastDir; } OpenData, *OpenDataPtr, **OpenDataHandle; //=================================================================================== // SaveData: Contains options information that is set from within the Save dialog. //=================================================================================== typedef struct { Boolean preview, close, palette, icons; short cropWhat; ImageFormatPtr format; ImageFormatPtr formatList[kFileFormats]; ImageHandle image; MenuHandle menuHandle; MenuHandle cropHandle; } SaveData, *SaveDataPtr, **SaveDataHandle; //===================================================================================== // Global variables local to this module //===================================================================================== static DlgHookYDUPP gOpenDialogHook = nil, gSaveDialogHook = nil; static FileFilterYDUPP gOpenFileFilter = nil; static OpenData gOpenData; static SaveData gSaveData; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static void InitSaveMenu(ImageHandle theImage, DialogPtr theDialog); static void DoPageSetup(void); //=================================================================================== // void HandleFileChoice(short theItem) //=================================================================================== // Dispatches selections from the File menu to the appropriate function. //=================================================================================== void HandleFileChoice(short theItem) { switch (theItem) { case fileImportItem: gOpenData.showAll = true; DoOpenDialog(); break; case fileOpenItem: gOpenData.showAll = false; DoOpenDialog(); break; case fileCloseItem: SendCloseWindow(FWFrontWindow()); break; case fileCloseAllItem: SendCloseWindow((WindowPtr)kAEAll); break; case fileSaveItem: DoSaveDialog(); break; case fileSlideItem: SendCreateWindow(kSlideShowDialogID); break; case fileStartSlideItem: if (gSlideShow) gPendingButton = kPauseButton; else SendSlideShow(); break; case fileEndSlideItem: gPendingButton = kStopButton; break; case filePageSetupItem: DoPageSetup(); break; case filePrintItem: if (FrontImage()) SendPrintDocument(FrontImage()); break; case filePrefsItem: SendCreateWindow(kPrefsDialogID); break; case fileQuitItem: SendQuitApplication(); break; } } /* * DoOpenDialog() * * Purpose: Presents the JPEGView custom open dialog & sends the * open document AppleEvent * Inputs: none * Returns: nothing * */ void DoOpenDialog(void) { Point where = CenterDialogWhere((gQTVersion) ? rOpenDialog : rOpenDialogNoQT); StandardFileReply reply; StartSpinning(); PushPort(); MySetPort(nil); if (!gOpenFileFilter) gOpenFileFilter = NewFileFilterYDProc((ProcPtr)OpenFileFilter); if (!gOpenDialogHook) gOpenDialogHook = NewDlgHookYDProc((ProcPtr)OpenDialogHook); RequestForeground(); if (gQTVersion) CustomGetFilePreview(gOpenFileFilter, -1, 0, &reply, rOpenDialog, where, gOpenDialogHook, gOpenSaveModalFilter, nil, nil, &reply); else CustomGetFile(gOpenFileFilter, -1, 0, &reply, rOpenDialogNoQT, where, gOpenDialogHook, gOpenSaveModalFilter, nil, nil, &reply); PopPort(); if (reply.sfGood) SendOpenDocument(&reply.sfFile); } /* * OpenSaveModalFilter(theDialog, theEvent, itemHit, yourDataPtr) * * Purpose: Filter for handling update events * Inputs: theDialog = pointer to the dialog * theEvent = pointer to an event record * itemHit = the item number that was "hit" * yourDataPtr = the refcon * Returns: true if we want ModalDialog to continue processing the event * */ extern pascal Boolean OpenSaveModalFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit, void *yourDataPtr) { #if applec #pragma unused(theDialog, itemHit, yourDataPtr) #endif Boolean isDialogEvent = IsDialogEvent(theEvent); switch (theEvent->what) { case updateEvt: if (isDialogEvent) HandleUpdateDialog(theEvent); else HandleUpdateEvent(theEvent); break; case activateEvt: if (isDialogEvent) HandleActivateDialog(theEvent); else HandleActivateEvent(theEvent); break; } return false; } /* * OpenFileFilter(pb, dummy) * * Purpose: Called by CustomGetFilePreview to allow us to filter out certain types * of files; here, depending on the status of the Show All Files button, * we either allow all files or only PICT/JFIF/JPEG/GIFf files * Inputs: pb = parameter block for the current file * dummy = a dummy reference constant * Returns: false to include the file, true otherwise * */ pascal Boolean OpenFileFilter(CInfoPBPtr pb, Boolean *dummy) { #if applec #pragma unused(dummy) #endif OSType theType = pb->hFileInfo.ioFlFndrInfo.fdType; if (pb->dirInfo.ioDrUsrWds.frFlags & fInvisible) return true; return !((pb->hFileInfo.ioFlAttrib & 0x10) || ValidType(theType) || gOpenData.showAll); } extern Boolean ValidType(OSType theType) { short i; for (i = 0; i < kFileFormats; i++) if (gFormat[i]->inType == theType || gFormat[i]->altInType == theType) return true; return false; } /* * OpenDialogHook(item, theDialog, dummy) * * Purpose: Called by CustomGetFilePreview to allow us to respond to our custom * dialog items; here we have only one, the Show All Files button * Inputs: item = the dialog item number that was hit * theDialog = pointer to the dialog window record * dummy = dummy reference constant * Returns: the item that was hit, or sfHookRebuildList to redisply the files * */ pascal short OpenDialogHook(short item, DialogPtr theDialog, long dummy) { static short gLastItem = 0, gLastVRefNum = 555; SysEnvRec theEnvirons; if (GetWRefCon(theDialog) != sfMainDialogRefCon) return item; if (gLastItem == sfItemEjectButton) { SysEnvirons(1, &theEnvirons); if (theEnvirons.sysVRefNum != gLastVRefNum) { UnmountVol(0, gLastVRefNum); Eject(0, gLastVRefNum); } } switch (item) { case sfHookFirstCall: HiliteMenu(0); FWDeactivate(); StopSpinning(&qd.arrow); break; case sfHookLastCall: FWActivate(); break; case openScanButton: StartSpinning(); ScanDirFiles(); DisableDControl(theDialog, openScanButton); StopSpinning(&qd.arrow); item = sfHookRebuildList; break; default: if ((gOpenData.lastVRef != -LMGetSFSaveDisk()) || (gOpenData.lastDir != LMGetCurDirStore())) EnableDControl(theDialog, openScanButton); break; } gLastVRefNum = ((StandardFileReply *)dummy)->sfFile.vRefNum; return gLastItem = item; } /* * ScanDirFiles() * * Purpose: Scans the current standard file directory for valid input files; if it * finds some, it changes their types accordingly * Inputs: none * Returns: nothing * */ void ScanDirFiles(void) { short theFile, fileType; CInfoPBRec block; Str255 fileName; OSType theType; FSSpec theSpec; FInfo theInfo; block.hFileInfo.ioNamePtr = fileName; block.hFileInfo.ioVRefNum = -LMGetSFSaveDisk(); block.hFileInfo.ioDirID = LMGetCurDirStore(); block.hFileInfo.ioFDirIndex = 1; while (PBGetCatInfo(&block, false) == noErr) { KeepSpinning(); theType = block.hFileInfo.ioFlFndrInfo.fdType; if (!(block.hFileInfo.ioFlAttrib & 0x10) && !ValidType(theType)) { FSMakeFSSpec(-LMGetSFSaveDisk(), block.hFileInfo.ioFlParID, fileName, &theSpec); if (FSpOpenDF(&theSpec, fsRdPerm, &theFile) == noErr) { fileType = IDImage(theFile, &theSpec); FSClose(theFile); if (fileType != kInvalidType) { FSpGetFInfo(&theSpec, &theInfo); theInfo.fdType = gFormat[fileType]->inType; theInfo.fdCreator = kCreator; FSpSetFInfo(&theSpec, &theInfo); } } } block.hFileInfo.ioFDirIndex++; block.hFileInfo.ioDirID = LMGetCurDirStore(); } gOpenData.lastDir = LMGetCurDirStore(); gOpenData.lastVRef = -LMGetSFSaveDisk(); ForceFolderUpdate(LMGetCurDirStore(), -LMGetSFSaveDisk()); } /* * DoSaveDialog() * * Purpose: Presents the JPEGView save dialog and sends the save document AppleEvent * Inputs: none * Returns: nothing * */ void DoSaveDialog(void) { Point where = CenterDialogWhere(rSaveDialog); ImageHandle theImage = FrontImage(); StandardFileReply reply; Str255 defaultName; OSErr theErr; StartSpinning(); gSaveData.image = theImage; gSaveData.format = (*theImage)->format; gSaveData.preview = gThePrefs.savePrev; gSaveData.icons = gThePrefs.makeIcons; gSaveData.close = gSaveData.palette = false; if ((*theImage)->qpalette && gSaveData.format->doesColors) { if (gThePrefs.saveQuant == sqAlways) gSaveData.palette = true; else if (gThePrefs.saveQuant == sqOnly) gSaveData.palette = !(*theImage)->ipalette; } gSaveData.cropWhat = kCropNothing; BlockMove((*theImage)->file.name, defaultName, 64); PushPort(); MySetPort(nil); FWDeactivate(); if (!gSaveDialogHook) gSaveDialogHook = NewDlgHookYDProc((ProcPtr)SaveDialogHook); RequestForeground(); CustomPutFile(gNullString, defaultName, &reply, ((*theImage)->compression == kJPEGCompression) ? rSaveDialog : rSimpleSaveDialog, where, gSaveDialogHook, gOpenSaveModalFilter, nil, nil, 0); PopPort(); if (reply.sfGood) { if (!reply.sfReplacing) { theErr = FSpCreate(&reply.sfFile, kCreator, gSaveData.format->outType, reply.sfScript); if (theErr != noErr) { StringError(errCantCreateFile, reply.sfFile.name); return; } } theErr = SendSaveDocument(&reply.sfFile, gSaveData.format->outType, gSaveData.preview && gQTVersion, gSaveData.palette && gSaveData.format->doesColors && (*gSaveData.image)->depth > 8 && (*gSaveData.image)->compression == kJPEGCompression, gSaveData.icons, gSaveData.cropWhat); if (theErr == noErr) { if (gSaveData.close) SendCloseWindow((*theImage)->window); } } } static void InitSaveMenu(ImageHandle theImage, DialogPtr theDialog) { short itemType, i, startValue = 1, pictItem = 0, count = 0; Handle itemHandle; Rect itemRect; // first get the handle to the pop-up menu GetDItem(theDialog, savePopupMenu, &itemType, &itemHandle, &itemRect); if (itemHandle) gSaveData.menuHandle = (*(PopupPrivateDataHandle)(*(ControlHandle)itemHandle)->contrlData)->mHandle; // now loop over all formats, adding them all, but only enabling those that match the // input format, as well as any formats that have a fix routine, but then only if the // image compression is 'jpeg' for (i = 0; i < kFileFormats; i++) { if (gFormat[i] == (*theImage)->format || (gFormat[i]->fix && (*theImage)->compression == kJPEGCompression)) { AppendMenu(gSaveData.menuHandle, (StringPtr)"\p( "); gSaveData.formatList[count] = gFormat[i]; SetItem(gSaveData.menuHandle, ++count, gFormat[i]->formatName); if (gFormat[i]->outType == kPICTType) pictItem = count; if (gFormat[i] == (*theImage)->format) startValue = count; if (Banded(theImage) && !gFormat[i]->doesBanded) continue; EnableItem(gSaveData.menuHandle, count); } } if (gThePrefs.savePICT && (*theImage)->format->inType == kJPEGType) { startValue = pictItem; gSaveData.format = &gPICTFormat; } SetCtlMax((ControlHandle)itemHandle, count); SetCtlValue((ControlHandle)itemHandle, startValue); // next get the handle to the cropping pop-up menu GetDItem(theDialog, saveCropMenu, &itemType, &itemHandle, &itemRect); if (itemHandle) gSaveData.cropHandle = (*(PopupPrivateDataHandle)(*(ControlHandle)itemHandle)->contrlData)->mHandle; } /* * UpdateSaveButtons(theDialog) * * Purpose: Updates the state of the custom buttons in the save dialog * Inputs: theDialog * Returns: nothing * */ void UpdateSaveButtons(DialogPtr theDialog) { ImageHandle theImage = gSaveData.image; Boolean enabled; SetDCtlValue(theDialog, saveCloseBox, gSaveData.close); enabled = (gQTVersion != 0); if (enabled) EnableDControl(theDialog, savePreviewBox); else DisableDControl(theDialog, savePreviewBox); SetDCtlValue(theDialog, savePreviewBox, gSaveData.preview && enabled); enabled = gSaveData.format->doesColors && (*gSaveData.image)->depth > 8 && (*gSaveData.image)->compression == kJPEGCompression; if (enabled) EnableDControl(theDialog, savePaletteBox); else DisableDControl(theDialog, savePaletteBox); SetDCtlValue(theDialog, savePaletteBox, gSaveData.palette && enabled); SetDCtlValue(theDialog, saveIconsBox, gSaveData.icons); if (!gSaveData.icons && gSaveData.cropWhat == kCropIcon) SetDCtlValue(theDialog, saveCropMenu, kCropNothing + 1); if (gSaveData.icons) EnableItem(gSaveData.cropHandle, kCropIcon + 1); else DisableItem(gSaveData.cropHandle, kCropIcon + 1); } /* * SaveDialogHook(item, theDialog, dummy) * * Purpose: Called by CustomPutFile to allow us to respond to our custom * dialog items; here we have only one, the Show All Files button * Inputs: item = the dialog item number that was hit * theDialog = pointer to the dialog window record * dummy = dummy reference constant * Returns: the item that was hit * */ pascal short SaveDialogHook(short item, DialogPtr theDialog, long dummy) { #if applec #pragma unused(dummy) #endif short newValue; if (GetWRefCon(theDialog) != sfMainDialogRefCon) return item; switch (item) { case sfHookFirstCall: SetItemHandle(theDialog, saveLineUser1, (Handle)gLineItem); SetItemHandle(theDialog, saveLineUser2, (Handle)gLineItem); SetItemHandle(theDialog, saveLineUser3, (Handle)gLineItem); if (!AntsHaveSelection((*gSaveData.image)->ants)) DisableDControl(theDialog, saveCropMenu); InitSaveMenu(gSaveData.image, theDialog); UpdateSaveButtons(theDialog); FWDeactivate(); StopSpinning(&qd.arrow); return item; case sfHookLastCall: FWActivate(); return item; case saveCloseBox: gSaveData.close = !gSaveData.close; break; case savePopupMenu: newValue = GetDCtlValue(theDialog, savePopupMenu); gSaveData.format = gSaveData.formatList[newValue - 1]; break; case savePreviewBox: gSaveData.preview = !gSaveData.preview; break; case savePaletteBox: gSaveData.palette = !gSaveData.palette; break; case saveIconsBox: gSaveData.icons = !gSaveData.icons; break; case saveCropMenu: gSaveData.cropWhat = GetDCtlValue(theDialog, saveCropMenu) - 1; break; default: return item; } UpdateSaveButtons(theDialog); return sfHookNullEvent; } static void DoPageSetup(void) { PrOpen(); if (!gPrintRecord) { if (LoadPrefsHandle(kPrefsPrintType, 0, (Handle *)&gPrintRecord) != noErr) { if (!(gPrintRecord = (THPrint)NewHandle(sizeof(TPrint)))) { MinorError(errNoMemory); return; } PrintDefault(gPrintRecord); } else PrValidate(gPrintRecord); } FWDeactivate(); PrStlDialog(gPrintRecord); FWActivate(); PrClose(); SavePrefsHandle(kPrefsPrintType, 0, (Handle)gPrintRecord); } \ No newline at end of file diff --git a/Source/C/FillHistogram16.c b/Source/C/FillHistogram16.c new file mode 100644 index 0000000..9439c5f --- /dev/null +++ b/Source/C/FillHistogram16.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void FillHistogram16(FillDataPtr theData) register ushort *bp; register ulong adr; register ushort w; while (theData->height--) { bp = (ushort *)theData->baseAdr; for (w = 0; w < theData->width; w++) { adr = *bp++; adr &= 0x00007fff; if (!(++theData->histogram[adr])) theData->histogram[adr]--; } theData->baseAdr += theData->rowBytes; } \ No newline at end of file diff --git a/Source/C/FillHistogram32.c b/Source/C/FillHistogram32.c new file mode 100644 index 0000000..a6cde75 --- /dev/null +++ b/Source/C/FillHistogram32.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // void FillHistogram32(FillDataPtr theData) register ulong r, g, b; register ulong *bp; register ushort w; while (theData->height--) { bp = (ulong *)theData->baseAdr; for (w = 0; w < theData->width; w++) { r = g = b = *bp++; r >>= 9; r &= 0x00007c00; g >>= 6; g &= 0x000003e0; r += g; b >>= 3; b &= 0x0000001f; r += b; if (!(++theData->histogram[r])) theData->histogram[r]--; } theData->baseAdr += theData->rowBytes; } \ No newline at end of file diff --git a/Source/C/FloatingWindows.c b/Source/C/FloatingWindows.c new file mode 100644 index 0000000..7d97809 --- /dev/null +++ b/Source/C/FloatingWindows.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //=================================================================================== // Includes specific to this module //=================================================================================== #include "FloatingWindows.h" //=================================================================================== // Local constants and macros //=================================================================================== enum { kWindowType = 'WIND', kFloatingWindowID = 128 }; #define isFloating(win) (WindowKind(win) == floatingWindowKind) //===================================================================================== // Global variables local to this module //===================================================================================== static WindowPtr gOldTop, gDummyWindow = nil; static RgnHandle gSaveRgn = nil; //=================================================================================== // Local functions //=================================================================================== static void FWRemoveFloats(void); static void FWRestoreFloats(Boolean redraw); static void FWInsertDummyWindow(WindowPtr behindWindow); static void FWRemoveDummyWindow(void); static Boolean isDialog(WindowPtr win); //=================================================================================== // void FWActivate(void) //=================================================================================== // Activates all floating windows and the frontmost document window. //=================================================================================== extern void FWActivate(void) { WindowPtr fwindow = FWTopFloatingWindow(), window = FWTopWindow(); while (fwindow) { if (isFloating(fwindow)) HiliteWindow(fwindow, true); fwindow = NextWindow(fwindow); } while (window && !WindowVisible(window)) window = NextWindow(window); if (window) { EventRecord theEvent; HiliteWindow(window, true); theEvent.what = activateEvt; theEvent.message = (long)window; theEvent.modifiers = 1; HandleActivateEvent(&theEvent); } } //=================================================================================== // void FWDeactivate(void) //=================================================================================== // Deactivates all floating windows and the frontmost document window. //=================================================================================== extern void FWDeactivate(void) { WindowPtr fwindow = FWTopFloatingWindow(), window = FWTopWindow(); while (fwindow) { if (isFloating(fwindow)) HiliteWindow(fwindow, false); fwindow = NextWindow(fwindow); } while (window && !WindowVisible(window)) window = NextWindow(window); if (window) { EventRecord theEvent; HiliteWindow(window, false); theEvent.what = activateEvt; theEvent.message = (long)window; theEvent.modifiers = 0; HandleActivateEvent(&theEvent); } } //=================================================================================== // void FWHideFloatingWindows(void) //=================================================================================== // Hides all floating windows. //=================================================================================== extern void FWHideFloatingWindows(void) { WindowPtr theWindow = FWTopFloatingWindow(); while (theWindow) { if (isFloating(theWindow) && WindowVisible(theWindow)) ShowHide(theWindow, false); else if (!isFloating(theWindow) && WindowHilited(theWindow)) HiliteWindow(theWindow, false); theWindow = NextWindow(theWindow); } } //=================================================================================== // void FWShowFloatingWindows(void) //=================================================================================== // Shows all floating windows. //=================================================================================== extern void FWShowFloatingWindows(void) { WindowPtr theWindow = FWBottomFloatingWindow(); WindowPtr frontWindow = FWFrontWindow(); WindowPtr lastFloating = nil; Boolean frontDialog = isDialog(frontWindow); Boolean hilited = false; if (theWindow) { FWInsertDummyWindow(theWindow); theWindow = FWTopFloatingWindow(); while (theWindow) { if (isFloating(theWindow)) { if (!WindowVisible(theWindow)) { ShowHide(theWindow, true); HiliteWindow(theWindow, !gInBackground && !frontDialog); } lastFloating = theWindow; } if (!isFloating(theWindow) && !hilited) { HiliteWindow(theWindow, !gInBackground && !frontDialog); hilited = true; } theWindow = NextWindow(theWindow); } FWRemoveDummyWindow(); } if (!frontDialog) { theWindow = FrontWindow(); if (theWindow && !isFloating(theWindow) && lastFloating) SendBehind(theWindow, lastFloating); } } //=================================================================================== // WindowPtr FWGetNewFloatingWindow(short resID, Ptr wStorage, WindowPtr behind) //=================================================================================== // Creates a new floating window, based on a given resource definition. //=================================================================================== extern WindowPtr FWGetNewFloatingWindow(short resID, Ptr wStorage, WindowPtr behind) { WindowPtr theWindow; if (behind != (WindowPtr)-1 && (!behind || !isFloating(behind))) { behind = FWBottomFloatingWindow(); if (!behind) behind = (WindowPtr)-1; } FWInsertDummyWindow(behind); theWindow = GetNewCWindow(resID, wStorage, behind); if (theWindow) SetWindowKind(theWindow, floatingWindowKind); FWRemoveDummyWindow(); return theWindow; } //=================================================================================== // WindowPtr FWNewFloatingWindow(Ptr wStorage, Rect *rBounds, Str255 title, // Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, // long refCon) //=================================================================================== // Creates a new floating window. //=================================================================================== extern WindowPtr FWNewFloatingWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon) { WindowPtr theWindow; if (behind != (WindowPtr)-1 && (!behind || !isFloating(behind))) { behind = FWBottomFloatingWindow(); if (!behind) behind = (WindowPtr)-1; } FWInsertDummyWindow(behind); theWindow = NewCWindow(wStorage, rBounds, title, visFlag, wDefProcID, behind, goAwayFlag, refCon); if (theWindow) SetWindowKind(theWindow, floatingWindowKind); FWRemoveDummyWindow(); return theWindow; } //=================================================================================== // short FWAlert(short alertID, ModalFilterProcPtr filterProc) //=================================================================================== // Displays a generic alert in the floating window environment. //=================================================================================== extern short FWAlert(short alertID, ModalFilterUPP filterProc) { short theItem; FWDeactivate(); theItem = Alert(alertID, filterProc); FWActivate(); return theItem; } //=================================================================================== // short FWCautionAlert(short alertID, ModalFilterProcPtr filterProc) //=================================================================================== // Displays a caution alert in the floating window environment. //=================================================================================== extern short FWCautionAlert(short alertID, ModalFilterUPP filterProc) { short theItem; FWDeactivate(); theItem = CautionAlert(alertID, filterProc); FWActivate(); return theItem; } //=================================================================================== // short FWNoteAlert(short alertID, ModalFilterProcPtr filterProc) //=================================================================================== // Displays a note alert in the floating window environment. //=================================================================================== extern short FWNoteAlert(short alertID, ModalFilterUPP filterProc) { short theItem; FWDeactivate(); theItem = NoteAlert(alertID, filterProc); FWActivate(); return theItem; } //=================================================================================== // short FWStopAlert(short alertID, ModalFilterProcPtr filterProc) //=================================================================================== // Displays a stop alert in the floating window environment. //=================================================================================== extern short FWStopAlert(short alertID, ModalFilterUPP filterProc) { short theItem; FWDeactivate(); theItem = StopAlert(alertID, filterProc); FWActivate(); return theItem; } //=================================================================================== // void FWCloseDialog(DialogPtr theDialog) //=================================================================================== // Closes a dialog in the floating window environment. //=================================================================================== extern void FWCloseDialog(DialogPtr theDialog) { CloseDialog(theDialog); if (!FWTopDialog()) FWActivate(); } //=================================================================================== // void FWDisposeDialog(DialogPtr theDialog) //=================================================================================== // Disposes of a dialog in the floating window environment. //=================================================================================== extern void FWDisposeDialog(DialogPtr theDialog) { DisposeDialog(theDialog); if (!FWTopDialog()) FWActivate(); } //=================================================================================== // Boolean FWDialogSelect(EventRecord *theEvent, DialogPtr *whichDlog, short *itemHit) //=================================================================================== // Handles events in dialog within a floating window environment. //=================================================================================== extern Boolean FWDialogSelect(EventRecord *theEvent, DialogPtr *whichDlog, short *itemHit) { Boolean theAnswer; FWRemoveFloats(); theAnswer = DialogSelect(theEvent, whichDlog, itemHit); FWRestoreFloats(false); return theAnswer; } //=================================================================================== // Boolean FWIsDialogEvent(EventRecord *theEvent) //=================================================================================== // Returns true if the given event was associated with a dialog. //=================================================================================== extern Boolean FWIsDialogEvent(EventRecord *theEvent) { WindowPtr theWindow; Boolean theAnswer; short thePart; thePart = FindWindow(theEvent->where, &theWindow); if (!isFloating(theWindow)) FWRemoveFloats(); theAnswer = IsDialogEvent(theEvent); if (!isFloating(theWindow)) FWRestoreFloats(false); return theAnswer; } //=================================================================================== // DialogPtr FWGetNewDialog(short dlgRsrcID, Ptr dStorage, WindowPtr behind) //=================================================================================== // Creates a new dialog from a resource in the floating window environment. //=================================================================================== extern DialogPtr FWGetNewDialog(short dlgRsrcID, Ptr dStorage, WindowPtr behind) { Boolean floatingTop = (GetFirstWindow() && isFloating(GetFirstWindow())); DialogTHndl theTemplate = (DialogTHndl)GetResource('DLOG', dlgRsrcID); Boolean modalDialog = false; DialogPtr theDialog; if (theTemplate) { modalDialog = ((*theTemplate)->procID >= dBoxProc && (*theTemplate)->procID <= altDBoxProc) || (*theTemplate)->procID == movableDBoxProc; if (modalDialog) FWDeactivate(); ReleaseResource((Handle)theTemplate); } if (!modalDialog && floatingTop) FWRemoveFloats(); theDialog = GetNewDialog(dlgRsrcID, dStorage, behind); if (!modalDialog && floatingTop) FWRestoreFloats(true); return theDialog; } //=================================================================================== // DialogPtr FWNewCDialog(Ptr dStorage, Rect *wRect, Str255 title, Boolean visFlag, // short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon, // Handle itemList) //=================================================================================== // Creates a new color dialog window in the floating window environment. //=================================================================================== extern DialogPtr FWNewCDialog(Ptr dStorage, Rect *wRect, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon, Handle itemList) { FWDeactivate(); return NewCDialog(dStorage, wRect, title, visFlag, wDefProcID, behind, goAwayFlag, refCon, itemList); } //=================================================================================== // DialogPtr FWNewDialog(Ptr dStorage, Rect *wRect, Str255 title, Boolean visFlag, // short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon, // Handle itemList) //=================================================================================== // Creates a new B&W dialog window in the floating window environment. //=================================================================================== extern DialogPtr FWNewDialog(Ptr dStorage, Rect *wRect, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon, Handle itemList) { FWDeactivate(); return NewDialog(dStorage, wRect, title, visFlag, wDefProcID, behind, goAwayFlag, refCon, itemList); } //=================================================================================== // void FWCloseWindow(WindowPtr theWindow) //=================================================================================== // Closes a window in the floating window environment. //=================================================================================== extern void FWCloseWindow(WindowPtr theWindow) { Boolean visible = WindowVisible(theWindow); Boolean floating = isFloating(theWindow); if (!floating && visible) FWRemoveFloats(); CloseWindow(theWindow); if (!floating && visible) FWRestoreFloats(true); } //=================================================================================== // void FWDisposeWindow(WindowPtr theWindow) //=================================================================================== // Disposes of a window in the floating window environment. //=================================================================================== extern void FWDisposeWindow(WindowPtr theWindow) { Boolean visible = WindowVisible(theWindow); Boolean floating = isFloating(theWindow); if (!floating && visible) FWRemoveFloats(); DisposeWindow(theWindow); if (!floating && visible) FWRestoreFloats(true); } //=================================================================================== // void FWDragWindow(WindowPtr theWindow, Point startPoint, Rect *limitRect) //=================================================================================== // Handles dragging a window in the floating window environment. //=================================================================================== extern void FWDragWindow(WindowPtr theWindow, Point startPoint, Rect *limitRect) { GDHandle oldGDevice; uchar theKeys[16]; GrafPort tempPort; WindowPtr window; CGrafPtr oldPort; RgnHandle theRgn; Point oldPos; long newPos; GetKeys((long *)theKeys); if ((theKeys[0x37 >> 3] >> (0x37 & 7)) & 1) DragWindow(theWindow, startPoint, limitRect); else { if (theWindow != FWFrontWindow() && theWindow != FrontWindow()) FWSelectWindow(theWindow); if (!StillDown()) return; oldPos = TopLeft((*GetContRgn(theWindow))->rgnBBox); GetGWorld(&oldPort, &oldGDevice); theRgn = NewRgn(); if (theRgn) { CopyRgn(GetStrucRgn(theWindow), theRgn); OpenPort(&tempPort); CopyRgn(GetGrayRgn(), tempPort.visRgn); if (!isFloating(theWindow) && !isDialog(theWindow)) { window = FWTopFloatingWindow(); while (window && window != theWindow) { if (WindowVisible(window)) DiffRgn(tempPort.visRgn, GetStrucRgn(window), tempPort.visRgn); window = NextWindow(window); } } tempPort.portRect = (*tempPort.visRgn)->rgnBBox; SetGWorld((CGrafPtr)&tempPort, nil); newPos = DragGrayRgn(theRgn, startPoint, limitRect, limitRect, 0, nil); ClosePort(&tempPort); SetGWorld(oldPort, oldGDevice); if (newPos != 0x80008000) { oldPos.h += newPos & 0xffff; oldPos.v += (newPos >> 16) & 0xffff; FWMoveWindow(theWindow, oldPos.h, oldPos.v, false); } DisposeRgn(theRgn); } } } //=================================================================================== // WindowPtr FWFrontWindow(void) //=================================================================================== // Returns the frontmost non-floating window. //=================================================================================== extern WindowPtr FWFrontWindow(void) { WindowPtr theWindow; if (theWindow = FWTopDialog()) { while (theWindow && !WindowVisible(theWindow)) theWindow = NextWindow(theWindow); if (theWindow && !isFloating(theWindow)) return theWindow; } if (theWindow = FWTopWindow()) { while (theWindow && !WindowVisible(theWindow)) theWindow = NextWindow(theWindow); } return theWindow; } //=================================================================================== // WindowPtr FWGetNewCWindow(short resID, Ptr wStorage, WindowPtr behind) //=================================================================================== // Gets a new color window from a resource. //=================================================================================== extern WindowPtr FWGetNewCWindow(short resID, Ptr wStorage, WindowPtr behind) { Boolean floatingTop = (GetFirstWindow() && isFloating(GetFirstWindow())); WindowPtr theWindow; if (floatingTop) FWRemoveFloats(); theWindow = GetNewCWindow(resID, wStorage, behind); if (floatingTop) FWRestoreFloats(true); return theWindow; } //=================================================================================== // WindowPtr FWGetNewWindow(short resID, Ptr wStorage, WindowPtr behind) //=================================================================================== // Gets a new B&W window from a resource. //=================================================================================== extern WindowPtr FWGetNewWindow(short resID, Ptr wStorage, WindowPtr behind) { Boolean floatingTop = (GetFirstWindow() && isFloating(GetFirstWindow())); WindowPtr theWindow; if (floatingTop) FWRemoveFloats(); theWindow = GetNewWindow(resID, wStorage, behind); if (floatingTop) FWRestoreFloats(true); return theWindow; } //=================================================================================== // void FWHideWindow(WindowPtr theWindow) //=================================================================================== // Hides the window. //=================================================================================== extern void FWHideWindow(WindowPtr theWindow) { Boolean visible = WindowVisible(theWindow); Boolean floating = isFloating(theWindow); if (!floating && visible) FWRemoveFloats(); HideWindow(theWindow); if (!floating && visible) FWRestoreFloats(true); } //=================================================================================== // void FWMoveWindow(WindowPtr theWindow, short hGlobal, short vGlobal, Boolean front) //=================================================================================== // Moves a window to the specified point on the screen. //=================================================================================== extern void FWMoveWindow(WindowPtr theWindow, short hGlobal, short vGlobal, Boolean front) { Boolean floating = isFloating(theWindow); if (!floating) FWRemoveFloats(); else FWInsertDummyWindow(nil); MoveWindow(theWindow, hGlobal, vGlobal, front); if (!floating) FWRestoreFloats(true); else FWRemoveDummyWindow(); } //=================================================================================== // WindowPtr FWNewCWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, // short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon) //=================================================================================== // Creates a new color window from all the good information presented here. //=================================================================================== extern WindowPtr FWNewCWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon) { Boolean floatingTop = (GetFirstWindow() && isFloating(GetFirstWindow())); WindowPtr theWindow; if (floatingTop) FWRemoveFloats(); theWindow = NewCWindow(wStorage, rBounds, title, visFlag, wDefProcID, behind, goAwayFlag, refCon); if (floatingTop) FWRestoreFloats(true); return theWindow; } //=================================================================================== // WindowPtr FWNewWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, // short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon) //=================================================================================== // Creates a new B&W window from all the good information presented here. //=================================================================================== extern WindowPtr FWNewWindow(Ptr wStorage, Rect *rBounds, Str255 title, Boolean visFlag, short wDefProcID, WindowPtr behind, Boolean goAwayFlag, long refCon) { Boolean floatingTop = (GetFirstWindow() && isFloating(GetFirstWindow())); WindowPtr theWindow; if (floatingTop) FWRemoveFloats(); theWindow = NewWindow(wStorage, rBounds, title, visFlag, wDefProcID, behind, goAwayFlag, refCon); if (floatingTop) FWRestoreFloats(true); return theWindow; } //=================================================================================== // void FWSelectWindow(WindowPtr theWindow) //=================================================================================== // Selects a window and brings it to the front of its layer. //=================================================================================== extern void FWSelectWindow(WindowPtr theWindow) { Boolean floating = isFloating(theWindow); if (floating && gInBackground) return; if (!floating) FWRemoveFloats(); else FWInsertDummyWindow(nil); SelectWindow(theWindow); if (!floating) FWRestoreFloats(true); else FWRemoveDummyWindow(); } //=================================================================================== // void FWShowWindow(WindowPtr theWindow) //=================================================================================== // Makes a window visible again. //=================================================================================== extern void FWShowWindow(WindowPtr theWindow) { WindowPtr frontWindow = FWFrontWindow(), realFrontWindow = FrontWindow(); Boolean floating = isFloating(theWindow); if (floating && gInBackground) return; if (!floating) FWRemoveFloats(); else FWInsertDummyWindow(nil); ShowWindow(theWindow); if (!floating) FWRestoreFloats(true); else FWRemoveDummyWindow(); if (floating && realFrontWindow && !isFloating(realFrontWindow)) SendBehind(realFrontWindow, theWindow); if (isFloating(theWindow) && !gInBackground && (!frontWindow || !isDialog(frontWindow))) HiliteWindow(theWindow, true); } //=================================================================================== // WindowPtr FWBottomDialog(void) //=================================================================================== // Returns a pointer to the bottommost dialog, or nil if none exist. //=================================================================================== extern WindowPtr FWBottomDialog(void) { WindowPtr theWindow = GetFirstWindow(), lastWindow = nil; while (theWindow) { if (isDialog(theWindow)) lastWindow = theWindow; theWindow = NextWindow(theWindow); } return lastWindow; } //=================================================================================== // WindowPtr FWBottomFloatingWindow(void) //=================================================================================== // Returns a pointer to the bottommost floating window, or nil if none exist. //=================================================================================== extern WindowPtr FWBottomFloatingWindow(void) { WindowPtr theWindow = GetFirstWindow(), lastWindow = nil; while (theWindow) { if (isFloating(theWindow)) lastWindow = theWindow; theWindow = NextWindow(theWindow); } return lastWindow; } //=================================================================================== // WindowPtr FWBottomWindow(void) //=================================================================================== // Returns a pointer to the bottommost standard window, or nil if none exist. //=================================================================================== extern WindowPtr FWBottomWindow(void) { WindowPtr theWindow = GetFirstWindow(), lastWindow = nil; while (theWindow) { if (!isFloating(theWindow) && !isDialog(theWindow)) lastWindow = theWindow; theWindow = NextWindow(theWindow); } return lastWindow; } //=================================================================================== // WindowPtr FWTopDialog(void) //=================================================================================== // Returns a pointer to the topmost dialog, or nil if none exist. //=================================================================================== extern WindowPtr FWTopDialog(void) { WindowPtr theWindow = GetFirstWindow(); while (theWindow && !isDialog(theWindow)) theWindow = NextWindow(theWindow); return theWindow; } //=================================================================================== // WindowPtr FWTopFloatingWindow(void) //=================================================================================== // Returns a pointer to the topmost floating window, or nil if none exist. //=================================================================================== extern WindowPtr FWTopFloatingWindow(void) { WindowPtr theWindow = GetFirstWindow(); while (theWindow && !isFloating(theWindow)) theWindow = NextWindow(theWindow); return theWindow; } //=================================================================================== // WindowPtr FWTopWindow(void) //=================================================================================== // Returns a pointer to the topmost standard window, or nil if none exist. //=================================================================================== extern WindowPtr FWTopWindow(void) { WindowPtr theWindow = GetFirstWindow(); while (theWindow && (isFloating(theWindow) || isDialog(theWindow))) theWindow = NextWindow(theWindow); return theWindow; } //=================================================================================== // void FWRemoveFloats(void) //=================================================================================== // This is the heart of our kludges to make floating windows work. This function // should be called before any operation manipulating standard windows. It simply // removes the floating windows from the window list, and subtracts their structure // regions from the GrayRgn of the desktop. Call FWRestoreFloats() to put // everything back to normal. //=================================================================================== static void FWRemoveFloats(void) { WindowPtr topFloat = FWTopFloatingWindow(), bottomDialog = FWBottomDialog(); if (!topFloat || bottomDialog) { gOldTop = (WindowPtr)-1; return; } if (!gSaveRgn) gSaveRgn = NewRgn(); gOldTop = GetFirstWindow(); CopyRgn(GetGrayRgn(), gSaveRgn); while (GetFirstWindow() && isFloating(GetFirstWindow())) { if (WindowVisible(GetFirstWindow())) DiffRgn(GetGrayRgn(), GetStrucRgn(GetFirstWindow()), GetGrayRgn()); SetFirstWindow(NextWindow(GetFirstWindow())); } } //=================================================================================== // void FWRestoreFloats(void) //=================================================================================== // This function should be called after FWRemoveFloats() and the appropriate window // manager function has been called. This function simply restores the GrayRgn of // the desktop and re-inserts the floating windows into the window list. Because a // palette change may have occurred, we also call PaintOne() on the titlebars of all // floating windows, to ensure that their colors are fixed up properly. //=================================================================================== static void FWRestoreFloats(Boolean redraw) { WindowPtr newTop, bottomFloat; RgnHandle theRgn; if (gOldTop == (WindowPtr)-1) return; XorRgn(gSaveRgn, GetGrayRgn(), gSaveRgn); UnionRgn(gSaveRgn, GetGrayRgn(), GetGrayRgn()); newTop = GetFirstWindow(); SetFirstWindow(gOldTop); if (bottomFloat = FWBottomFloatingWindow()) SetNextWindow(bottomFloat, newTop); newTop = GetFirstWindow(); if (redraw && newTop && isFloating(newTop)) { if (theRgn = NewRgn()) { while (isFloating(newTop)) { DiffRgn(GetStrucRgn(newTop), GetContRgn(newTop), theRgn); PaintOne((WindowPeek)newTop, theRgn); newTop = NextWindow(newTop); } DisposeRgn(theRgn); } } } //=================================================================================== // void FWInsertDummyWindow(WindowPtr behindWindow) //=================================================================================== // This function inserts a dummy window into the windowlist behind the specified // window. We use this function to prevent windows from unhiliting when we // manipulate the floating windows above them. //=================================================================================== static void FWInsertDummyWindow(WindowPtr behindWindow) { if (!gDummyWindow) { if (gDummyWindow = AllocateWindow()) { Rect theRect = { -32760, -32760, -32761, -32761 }; gDummyWindow = NewWindow(gDummyWindow, &theRect, gNullString, true, plainDBox, nil, false, 0); FWRemoveDummyWindow(); } } if (gDummyWindow) { if (behindWindow && (behindWindow != (WindowPtr)-1)) { SetNextWindow(gDummyWindow, NextWindow(behindWindow)); SetNextWindow(behindWindow, gDummyWindow); } else { SetNextWindow(gDummyWindow, GetFirstWindow()); SetFirstWindow(gDummyWindow); } } } //=================================================================================== // void FWRemoveDummyWindow(void) //=================================================================================== // This function removes the dummy window from the window list. //=================================================================================== static void FWRemoveDummyWindow(void) { WindowPtr theWindow, lastWindow = nil; if (GetFirstWindow() == gDummyWindow) SetFirstWindow(NextWindow(gDummyWindow)); else { for (theWindow = GetFirstWindow(); theWindow && (theWindow != gDummyWindow); theWindow = NextWindow(theWindow)) lastWindow = theWindow; if (lastWindow) SetNextWindow(lastWindow, NextWindow(gDummyWindow)); } } //=================================================================================== // void FWRemoveDummyWindow(void) //=================================================================================== // Returns true if the window is a modal dialog window. //=================================================================================== static Boolean isDialog(WindowPtr win) { if (WindowKind(win) == dialogKind) { short var = GetWVariant(win); if ((var >= dBoxProc && var <= altDBoxProc) || var == movableDBoxProc) return true; } return false; } //=================================================================================== // These functions serve as interfaces to Window Manager variables. //=================================================================================== extern WindowPtr GetFirstWindow(void) { return (WindowPtr)LMGetWindowList(); } extern WindowPtr NextWindow(WindowPtr theWindow) { return (WindowPtr)((WindowPeek)theWindow)->nextWindow; } extern short WindowKind(WindowPtr theWindow) { return ((WindowPeek)theWindow)->windowKind; } extern Boolean WindowVisible(WindowPtr theWindow) { return ((WindowPeek)theWindow)->visible; } extern Boolean WindowHilited(WindowPtr theWindow) { return ((WindowPeek)theWindow)->hilited; } extern RgnHandle GetStrucRgn(WindowPtr theWindow) { return ((WindowPeek)theWindow)->strucRgn; } extern RgnHandle GetContRgn(WindowPtr theWindow) { return ((WindowPeek)theWindow)->contRgn; } extern Boolean HasGoAway(WindowPtr theWindow) { return ((WindowPeek)theWindow)->goAwayFlag; } extern void SetWindowKind(WindowPtr theWindow, short theKind) { ((WindowPeek)theWindow)->windowKind = theKind; } extern void SetNextWindow(WindowPtr theWindow, WindowPtr nextWindow) { ((WindowPeek)theWindow)->nextWindow = (WindowPeek)nextWindow; } extern void SetFirstWindow(WindowPtr theWindow) { LMSetWindowList((WindowPeek)theWindow); } \ No newline at end of file diff --git a/Source/C/GIF.c b/Source/C/GIF.c new file mode 100644 index 0000000..2e82b9e --- /dev/null +++ b/Source/C/GIF.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "GIF.h" //===================================================================================== // GIFData: structure holding information needed to decompress a GIF image; passed // between the C and assembly language portions of this module. //===================================================================================== typedef struct GIFData { uchar *src; /* 0 */ uchar *dest; /* 4 */ uchar *stack; /* 8 */ uchar *end; /* 12 */ ulong *tree; /* 16 */ #if USE_ASM ulong store[12]; /* 20 */ // this is specific to the 68020 implementation #endif ushort charSize; /* 68 */ short width; /* 70 */ Boolean theReturn; /* 72 */ } GIFData, *GIFDataPtr; //===================================================================================== // GIFPrivates: private data structure for GIF images, maintained for each image. //===================================================================================== typedef struct GIFPrivates { long totalLines; } GIFPrivates, *GIFPrivatesPtr, **GIFPrivatesHandle; //===================================================================================== // Global variables local to this module //===================================================================================== static long gTotalLines, gCurrentLines; static GIFData gGIFData; static JVDrawParamsHandle gGIFParams; // globals specific to the C implementation of GIF decoding #if !USE_ASM static ushort gTreeSize, gCodeSize, gBytesLeft, gClearCode, gEndCode; static ushort gFirstCode, gLastCode; static ulong gBitBuffer, gBitsInBuffer; static uchar *gStack, *gInput; #endif //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static Size FindNextGIFImage(Handle theData, Size startOffset); static OSErr ExtractGIFComments(Handle theData, Handle *theComments); static GWorldPtr MakeGIFGWorld(Handle theHandle, uchar *theData); static PaletteHandle MakeGIFPalette(uchar *theData, short theSize); static CTabHandle MakeGIFCTable(uchar *theData); static OSErr DecompressGIFImage(uchar *theData, PixMapHandle srcPixMap, Rect *srcRect, Rect *dstRect, RgnHandle dstRgn, ICMProgressProcRecordPtr progProc); static Boolean DecodeInterlaced(uchar *theData, PixMapHandle srcPixMap, short iwidth, short iheight, Rect *sRect, short *rowCount, ICMProgressProcRecordPtr progProc); static Boolean DecodeNonInterlaced(uchar *theData, PixMapHandle srcPixMap, short iwidth, short iheight, Rect *sRect, short *rowCount, ICMProgressProcRecordPtr progProc); static Boolean DecodeRow(short width, uchar *src, uchar *dest); #if USE_ASM && !THINK_C extern void DoDecodeRow(GIFDataPtr theData); extern void DoDecodeDummyRow(GIFDataPtr theData); #else static void DoDecodeRow(GIFDataPtr theData); static void DoDecodeDummyRow(GIFDataPtr theData); #endif //===================================================================================== // Boolean idGIF(uchar *theData, long theSize) //===================================================================================== // Examines the given data and attempts to identify it as a GIF image. //===================================================================================== extern Boolean idGIF(uchar *theData, long theSize, short refNum, FSSpec *theSpec) { #if applec #pragma unused(refNum, theSpec) #endif return (theSize > 6 && theData[0] == 'G' && theData[1] == 'I' && theData[2] == 'F' && theData[3] == '8' && (theData[4] == '7' || theData[4] == '9') && theData[5] == 'a'); } //===================================================================================== // OSErr OpenGIF(ImageHandle theImage) //===================================================================================== // Initializes the image record for a GIF image. //===================================================================================== extern OSErr OpenGIF(ImageHandle theImage) { long theLen = GetHandleSize((*theImage)->data), totalLines; char hState = HGetState((*theImage)->data); Rect imageRect = { 0, 0, 0, 0 }; Size imageOffset; Handle theHandle; uchar *theData; if (!((*theImage)->privateData = NewHandleClear(sizeof(GIFPrivates)))) return memFullErr; HLock((*theImage)->data); theData = (uchar *)*(*theImage)->data; SetRect(&(*theImage)->grect, 0, 0, (theData[7] << 8) + theData[6], (theData[9] << 8) + theData[8]); (*theImage)->compression = kGIFType; BlockMove(gString[strLZWGIF], (*theImage)->desc.name, gString[strLZWGIF][0] + 1); imageOffset = FindNextGIFImage((*theImage)->data, 0); if (imageOffset != -1) { theData = (uchar *)*(*theImage)->data + imageOffset; if (theData[9] & 0x80) { (*theImage)->depth = (theData[9] & 7) + 1; (*theImage)->ipalette = MakeGIFPalette(theData + 10, (*theImage)->depth); } else { (*theImage)->depth = (*((uchar *)*(*theImage)->data + 10) & 7) + 1; (*theImage)->ipalette = MakeGIFPalette((uchar *)*(*theImage)->data + 13, (*theImage)->depth); } ExtractGIFComments((*theImage)->data, &theHandle); (*theImage)->comments = theHandle; imageRect.top = (theData[4] << 8) + theData[3]; imageRect.left = (theData[2] << 8) + theData[1]; imageRect.bottom = imageRect.top + (theData[8] << 8) + theData[7]; imageRect.right = imageRect.left + (theData[6] << 8) + theData[5]; totalLines = Height(&imageRect); (*theImage)->grect = imageRect; while ((imageOffset = FindNextGIFImage((*theImage)->data, imageOffset)) != -1) { theData = (uchar *)*(*theImage)->data + imageOffset; imageRect.top = (theData[4] << 8) + theData[3]; imageRect.left = (theData[2] << 8) + theData[1]; imageRect.bottom = imageRect.top + (theData[8] << 8) + theData[7]; imageRect.right = imageRect.left + (theData[6] << 8) + theData[5]; totalLines += Height(&imageRect); UnionRect(&imageRect, &(*theImage)->grect, &(*theImage)->grect); } } else return gIntError = errCorruptImage, codecBadDataErr; (*theImage)->qrect = (*theImage)->crect = (*theImage)->grect; HSetState((*theImage)->data, hState); (*(GIFPrivatesHandle)(*theImage)->privateData)->totalLines = totalLines; BlockMove(gString[strLZWGIF], (*theImage)->compressionDesc, *gString[strLZWGIF] + 1); return noErr; } //===================================================================================== // OSErr DrawGIF(Handle theHandle, JVDrawParamsHandle theParams) //===================================================================================== // Draws a GIF image, whose data is in theHandle, to the destination described in the // drawing parameters. //===================================================================================== extern OSErr DrawGIF(Handle theHandle, JVDrawParamsHandle theParams) { NestedProgress theProgress = (*theParams)->progress; long dataLen = GetHandleSize(theHandle); Rect srcRect = (*theParams)->bounds; char hState = HGetState(theHandle); PixMapHandle gifPixMap; Handle gifDataHandle; OSErr theErr = noErr; Size imageOffset = 0; GWorldPtr gifGWorld; uchar *dataStart; gTotalLines = (*(GIFPrivatesHandle)(*theParams)->privateData)->totalLines; gCurrentLines = 0; gGIFParams = theParams; gifDataHandle = NewHandleClear(4096 + 4096 * 4); if (!gifDataHandle) gifDataHandle = TempNewHandle(4096 + 4096 * 4, &theErr); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon); if (gifDataHandle && theErr == noErr) { HLockHi(gifDataHandle); HLockHi(theHandle); gGIFData.stack = (uchar *)StripAddress(*gifDataHandle); gGIFData.tree = (ulong *)(gGIFData.stack + 4096); imageOffset = FindNextGIFImage(theHandle, 0); if (imageOffset != -1) { do { dataStart = (uchar *)StripAddress(*theHandle) + imageOffset; if (gifGWorld = MakeGIFGWorld(theHandle, dataStart)) { gifPixMap = GetGWorldPixMap(gifGWorld); gGIFData.end = (uchar *)StripAddress(*theHandle) + dataLen; theErr = DecompressGIFImage(dataStart, gifPixMap, &srcRect, &srcRect, qd.thePort->visRgn, (ICMProgressProcRecordPtr)&theProgress); if ((*theParams)->progress.aborted) theErr = codecAbortErr; DisposeGWorld(gifGWorld); } else gIntError = errNoDrawMemory, theErr = memFullErr; if (theErr == noErr) imageOffset = FindNextGIFImage(theHandle, imageOffset); } while (theErr == noErr && imageOffset != -1); } else gIntError = errCorruptImage, theErr = codecBadDataErr; HSetState(theHandle, hState); DisposeHandle(gifDataHandle); } else gIntError = errNoDrawMemory, theErr = memFullErr; if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon); return theErr; } //===================================================================================== // Size FindNextGIFImage(Handle theData, Size startOffset) //===================================================================================== // Given a handle containing a GIF image and an offset into that handle's data, this // routine locates the next GIF image. The initial offset must either point to the // beginning of a GIF stream, or to a previously-found GIF image. //===================================================================================== static Size FindNextGIFImage(Handle theData, Size startOffset) { uchar *theStart = (uchar *)StripAddress(*theData), *theAdr; uchar *theEnd = theStart + GetHandleSize(theData); Size theSize; theAdr = theStart + startOffset; if (*theAdr == 'G') { // Skip over global color table and global screen descriptors here if (theAdr[10] & 0x80) theAdr += 3 * (1 << ((theAdr[10] & 7) + 1)); theAdr += 13; if (theAdr >= theEnd) return -1; } else if (*theAdr == 0x2c) { // Skip over previous image color table, descriptors, and data here if (theAdr[9] & 0x80) theAdr += 3 * (1 << ((theAdr[9] & 7) + 1)); theAdr += 11; while (theSize = *theAdr++) { theAdr += theSize; if (theAdr > theEnd) return -1; } } else return -1; // Skip over any other GIF89 extensions here while (*theAdr == 0x21) { theAdr += 2; while (theSize = *theAdr++) { theAdr += theSize; if (theAdr >= theEnd) return -1; } } // If the next code is not an image descriptor, forget it if (*theAdr != 0x2c) return -1; // Otherwise, return the offset of the image return (Size)(theAdr - theStart); } //===================================================================================== // OSErr ExtractGIFComments(Handle theData, Handle *theComments) //===================================================================================== // Extracts the raw comments contained in the given GIF data into a handle. //===================================================================================== static OSErr ExtractGIFComments(Handle theData, Handle *theComments) { char hState = HGetState(theData); uchar *theAdr = (uchar *)StripAddress(*theData); uchar *theEnd = theAdr + GetHandleSize(theData); Boolean isComment, bad = false; long theSize, weird, i; OSErr theErr = noErr; *theComments = nil; // Skip over global color table and global screen descriptors here if (theAdr[10] & 0x80) theAdr += 3 * (1 << ((theAdr[10] & 7) + 1)); theAdr += 13; // Loop over all data, including GIF89 extensions and image descriptors while (theAdr < theEnd && theErr == noErr) { // For extensions, skip it all if not a comment, or else accumulate the // data into the comments handle if (*theAdr == 0x21) { theAdr++; isComment = (*theAdr++ == 0xfe); while (theSize = *theAdr++) { if (isComment) { for (weird = i = 0; (i < theSize) && !bad; i++) { if (theAdr[i] >= 0x20 && theAdr[i] <= 0x7f) continue; else if (theAdr[i] == 0x0a) theAdr[i] = 0x0d; else if (theAdr[i] == 0x0d && theAdr[i + 1] == 0x0a) theAdr[++i] = 0x00; else weird++; } if (!bad) bad = (weird > (theSize >> 4)); if (bad) isComment = false; else { if (!*theComments) theErr = PtrToHand(theAdr, theComments, theSize); else theErr = PtrAndHand(theAdr, *theComments, theSize); } } theAdr += theSize; if (theAdr >= theEnd) break; } // For image descriptors, simply skip over all the extra data } else if (*theAdr == 0x2c) { if (theAdr[9] & 0x80) theAdr += 3 * (1 << ((theAdr[9] & 7) + 1)); theAdr += 11; while (theSize = *theAdr++) { theAdr += theSize; if (theAdr >= theEnd) break; } // Otherwise, we've hit the end; get out of here } else break; } HSetState(theData, hState); return theErr; } //===================================================================================== // PaletteHandle MakeGIFPalette(uchar *theData, short theSize) //===================================================================================== // Creates a palette for a GIF image, substituting white and black for the brightest // and darkest colors. //===================================================================================== static PaletteHandle MakeGIFPalette(uchar *theData, short theSize) { ushort dist, wdist = (10 * 256), bdist = (10 * 256); ushort whitest = 256, blackest = 256, i, cur; PaletteHandle theResult; RGBColor theColor; theSize = 1 << theSize; if (!(theResult = NewPalette(256, nil, pmTolerant, 0))) return nil; if (theSize == 256) { uchar *color = theData; for (i = 0; i < 256; i++) { dist = 3 * (ushort)color[0] + 6 * (ushort)color[1] + (ushort)color[2]; if (dist < bdist) { bdist = dist; blackest = i; } dist = (10 << 8) - dist; if (dist < wdist) { wdist = dist; whitest = i; } color += 3; } } theColor.red = theColor.green = theColor.blue = 0xffff; SetEntryColor(theResult, 0, &theColor); theColor.red = theColor.green = theColor.blue = 0; SetEntryColor(theResult, 1, &theColor); for (i = 0, cur = 2; i < theSize; i++) { if (i != blackest && i != whitest) { theColor.red = (ushort)(*theData << 8) + *theData; theData++; theColor.green = (ushort)(*theData << 8) + *theData; theData++; theColor.blue = (ushort)(*theData << 8) + *theData; theData++; SetEntryColor(theResult, cur++, &theColor); } } for ( ; cur < 256; cur++) { GetEntryColor(gColorPalette[8], cur, &theColor); SetEntryColor(theResult, cur, &theColor); } return theResult; } //===================================================================================== // GWorldPtr MakeGIFGWorld(Handle theHandle, uchar *theData) //===================================================================================== // Creates a suitably large offscreen GWorld for drawing bands of a GIF image into. //===================================================================================== static GWorldPtr MakeGIFGWorld(Handle theHandle, uchar *theData) { ushort theHeight = (theData[8] << 8) + theData[7]; ushort theWidth = (theData[6] << 8) + theData[5]; GWorldPtr theGWorld = nil; CTabHandle theColors; if (theData[9] & 0x80) theData += 10; else theData = (uchar *)*theHandle + 13; if (theColors = MakeGIFCTable(theData)) { theGWorld = NewTempGWorld(theWidth, theHeight, 8, theColors); DisposeHandle((Handle)theColors); } return theGWorld; } //===================================================================================== // CTabHandle MakeGIFCTable(uchar *theData) //===================================================================================== // Creates a color table handle for the given palette. //===================================================================================== static CTabHandle MakeGIFCTable(uchar *theData) { CTabHandle theColors; OSErr theErr = noErr; ColorSpec *ctData; short i; theColors = (CTabHandle)NewHandle(sizeof(ColorTable) + 255 * sizeof(ColorSpec)); if (!theColors) theColors = (CTabHandle)TempNewHandle(sizeof(ColorTable) + 255 * sizeof(ColorSpec), &theErr); if (theColors && theErr == noErr) { (*theColors)->ctSeed = GetCTSeed(); (*theColors)->ctFlags = 0x8000; (*theColors)->ctSize = 255; ctData = &(*theColors)->ctTable[0]; for (i = 0; i < 256; i++) { ctData->rgb.red = (ushort)(*theData++) << 8; ctData->rgb.green = (ushort)(*theData++) << 8; ctData->rgb.blue = (ushort)(*theData++) << 8; ctData++; } } else theColors = nil; return theColors; } //===================================================================================== // OSErr DecompressGIFImage(uchar *theData, PixMapHandle srcPixMap, Rect *srcRect, // Rect *dstRect, RgnHandle dstRgn, ICMProgressProcRecordPtr progProc) //===================================================================================== // Decompresses a single image in a GIF to the appropriate destination rectangle. //===================================================================================== static OSErr DecompressGIFImage(uchar *theData, PixMapHandle srcPixMap, Rect *srcRect, Rect *dstRect, RgnHandle dstRgn, ICMProgressProcRecordPtr progProc) { Rect imageSrcRect, imageDstRect, bandSrcRect, bandDstRect, localSrcRect; PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); short bandHeight = Height(&(*srcPixMap)->bounds), rowCount = 0; Boolean interlaced = theData[9] & 0x40, done = false; NestedProgress theProc = (*gGIFParams)->progress; OSErr theErr = noErr; // calculate the source & destination rectangle for this image imageSrcRect.top = (theData[4] << 8) + theData[3]; imageSrcRect.left = (theData[2] << 8) + theData[1]; imageSrcRect.bottom = imageSrcRect.top + (theData[8] << 8) + theData[7]; imageSrcRect.right = imageSrcRect.left + (theData[6] << 8) + theData[5]; imageDstRect = imageSrcRect; MapRect(&imageDstRect, srcRect, dstRect); // skip over the descriptor and local color table, if any if (theData[9] & 0x80) theData += 3 * (1 << ((theData[9] & 7) + 1)); theData += 10; // reset the data pointers and LZW decoder for non-interlaced images if (!interlaced) DecodeRow(Width(&imageSrcRect), theData, nil); // set up the progress function (*gGIFParams)->progress.begin = FixRatio(gCurrentLines, gTotalLines); (*gGIFParams)->progress.begin = theProc.begin + FixMul((*gGIFParams)->progress.begin, theProc.end - theProc.begin); (*gGIFParams)->progress.end = FixRatio(gCurrentLines + Height(&imageSrcRect), gTotalLines); (*gGIFParams)->progress.end = theProc.begin + FixMul((*gGIFParams)->progress.end, theProc.end - theProc.begin); if ((*gGIFParams)->progress.prog.progressProc) CallICMProgressProc((*gGIFParams)->progress.prog.progressProc, codecProgressUpdatePercent, (*gGIFParams)->progress.begin, (*gGIFParams)->progress.prog.progressRefCon); // initialize the band source and destination rectangles bandSrcRect = imageSrcRect; bandSrcRect.bottom = bandSrcRect.top + bandHeight; // now loop until we've drawn all the bands do { // decompress a band; for this we need the bandSrcRect relative to the // image rect at (0,0) localSrcRect = bandSrcRect; OffsetRect(&localSrcRect, -imageSrcRect.left, -imageSrcRect.top); LockPixels(srcPixMap); if (interlaced) done = DecodeInterlaced(theData, srcPixMap, Width(&imageSrcRect), Height(&imageSrcRect), &localSrcRect, &rowCount, progProc); else done = DecodeNonInterlaced(theData, srcPixMap, Width(&imageSrcRect), Height(&imageSrcRect), &localSrcRect, &rowCount, progProc); UnlockPixels(srcPixMap); // calculate the appropriate destination rectangle and CopyBits there bandDstRect = bandSrcRect; MapRect(&bandDstRect, srcRect, dstRect); if (!dstRgn || bandDstRect.bottom >= (*dstRgn)->rgnBBox.top) { char sState = HGetState((Handle)srcPixMap), dState = HGetState((Handle)dstPixMap); HLock((Handle)srcPixMap); HLock((Handle)dstPixMap); LockPixels(srcPixMap); OffsetRect(&localSrcRect, -localSrcRect.left, -localSrcRect.top); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &localSrcRect, &bandDstRect, srcCopy, dstRgn); UnlockPixels(srcPixMap); HSetState((Handle)dstPixMap, dState); HSetState((Handle)srcPixMap, sState); } if ((done && !interlaced) || (*gGIFParams)->progress.aborted || bandDstRect.bottom >= dstRect->bottom || (dstRgn && bandDstRect.bottom >= (*dstRgn)->rgnBBox.bottom)) break; // if we hit a bad spot of data, set the errors and break out if (!gGIFData.end && !done) { gIntError = errCorruptImage, theErr = codecBadDataErr; break; } // if we've drawn all we need to, exit prematurely if (dstRgn && bandDstRect.top > (*dstRgn)->rgnBBox.bottom) break; // otherwise, set up for the next band bandSrcRect.top += bandHeight; bandSrcRect.bottom += bandHeight; if (bandSrcRect.bottom > imageSrcRect.bottom) bandSrcRect.bottom = imageSrcRect.bottom; } while (bandDstRect.top < imageDstRect.bottom); // clean up after the progress function if ((*gGIFParams)->progress.prog.progressProc) CallICMProgressProc((*gGIFParams)->progress.prog.progressProc, codecProgressUpdatePercent, (*gGIFParams)->progress.end, (*gGIFParams)->progress.prog.progressRefCon); (*gGIFParams)->progress.begin = theProc.begin; (*gGIFParams)->progress.end = theProc.end; KeepSpinning(); gCurrentLines += Height(&imageSrcRect); // if we were aborted, signal the abort error return theErr; } //===================================================================================== // Boolean DecodeInterlaced(uchar *theData, PixMapHandle srcPixMap, short iwidth, // short iheight, Rect *sRect, ICMProgressProcRecordPtr progProc) //===================================================================================== // Organizes the decoding of an interlaced GIF image band. //===================================================================================== static Boolean DecodeInterlaced(uchar *theData, PixMapHandle srcPixMap, short imageWidth, short imageHeight, Rect *srcRect, short *rowCount, ICMProgressProcRecordPtr progProc) { static short gRowCount; uchar *baseAdr = (uchar *)GetPixBaseAddr(srcPixMap); long rowBytes = (*srcPixMap)->rowBytes & 0x3fff; uchar *theAdr; OSErr theErr; short row; // if the top of the source rectangle is 0, reset our row counter if (!srcRect->top) gRowCount = 0; // reset the data pointers and LZW decoder DecodeRow(imageWidth, theData, nil); // do the first set of interlacing (starting at row 0, every 8 rows) for (row = 0; row < imageHeight; row += 8) { if (row >= srcRect->top && row < srcRect->bottom) { theAdr = baseAdr + rowBytes * (row - srcRect->top); (*rowCount)++; if (!(*rowCount & 63) && progProc->progressProc) { theErr = (OSErr)CallICMProgressProc(progProc->progressProc, codecProgressUpdatePercent, FixRatio(*rowCount, imageHeight), progProc->progressRefCon); if (theErr == codecAbortErr) return true; } if (DecodeRow(imageWidth, theData, theAdr) || !gGIFData.end) return true; } else if (DecodeRow(imageWidth, theData, (uchar *)-1) || !gGIFData.end) return true; } // do the second set of interlacing (starting at row 4, every 8 rows) for (row = 4; row < imageHeight; row += 8) { if (row >= srcRect->top && row < srcRect->bottom) { theAdr = baseAdr + rowBytes * (row - srcRect->top); (*rowCount)++; if (!(*rowCount & 63) && progProc->progressProc) { theErr = (OSErr)CallICMProgressProc(progProc->progressProc, codecProgressUpdatePercent, FixRatio(*rowCount, imageHeight), progProc->progressRefCon); if (theErr == codecAbortErr) return true; } if (DecodeRow(imageWidth, theData, theAdr) || !gGIFData.end) return true; } else if (DecodeRow(imageWidth, theData, (uchar *)-1) || !gGIFData.end) return true; } // do the third set of interlacing (starting at row 2, every 4 rows) for (row = 2; row < imageHeight; row += 4) { if (row >= srcRect->top && row < srcRect->bottom) { theAdr = baseAdr + rowBytes * (row - srcRect->top); (*rowCount)++; if (!(*rowCount & 63) && progProc->progressProc) { theErr = (OSErr)CallICMProgressProc(progProc->progressProc, codecProgressUpdatePercent, FixRatio(*rowCount, imageHeight), progProc->progressRefCon); if (theErr == codecAbortErr) return true; } if (DecodeRow(imageWidth, theData, theAdr) || !gGIFData.end) return true; } else if (DecodeRow(imageWidth, theData, (uchar *)-1) || !gGIFData.end) return true; } // do the last set of interlacing (starting at row 1, every other row) for (row = 1; row < imageHeight; row += 2) { if (row >= srcRect->top && row < srcRect->bottom) { theAdr = baseAdr + rowBytes * (row - srcRect->top); (*rowCount)++; if (!(*rowCount & 63) && progProc->progressProc) { theErr = (OSErr)CallICMProgressProc(progProc->progressProc, codecProgressUpdatePercent, FixRatio(*rowCount, imageHeight), progProc->progressRefCon); if (theErr == codecAbortErr) return true; } if (DecodeRow(imageWidth, theData, theAdr) || !gGIFData.end) return true; } else if (DecodeRow(imageWidth, theData, (uchar *)-1) || !gGIFData.end) return true; } return false; } //===================================================================================== // Boolean DecodeNonInterlaced(uchar *theData, PixMapHandle srcPixMap, short imageWidth, // short imageHeight, Rect *srcRect, ICMProgressProcRecordPtr progProc) //===================================================================================== // Organizes the decoding of an interlaced GIF image band. //===================================================================================== static Boolean DecodeNonInterlaced(uchar *theData, PixMapHandle srcPixMap, short imageWidth, short imageHeight, Rect *srcRect, short *rowCount, ICMProgressProcRecordPtr progProc) { #if applec #pragma unused(srcRect) #endif uchar *baseAdr = (uchar *)GetPixBaseAddr(srcPixMap); long rowBytes = (*srcPixMap)->rowBytes & 0x3fff; short height = Height(&(*srcPixMap)->bounds); OSErr theErr; short row; for (row = 0; row < height; row++) { if (DecodeRow(imageWidth, theData, baseAdr) || !gGIFData.end) return true; baseAdr += rowBytes; (*rowCount)++; if (!(*rowCount & 63) && progProc->progressProc) { theErr = (OSErr)CallICMProgressProc(progProc->progressProc, codecProgressUpdatePercent, FixRatio(*rowCount, imageHeight), progProc->progressRefCon); if (theErr == codecAbortErr) return true; } } return false; } //===================================================================================== // Boolean DecodeRow(short width, uchar *src, uchar *dest) //===================================================================================== // Decodes a single row of a GIF image. //===================================================================================== static Boolean DecodeRow(short width, uchar *src, uchar *dest) { char mmuMode = true32b; gGIFData.width = width; gGIFData.src = src; gGIFData.dest = dest; SwapMMUMode(&mmuMode); if (dest != (uchar *)-1) DoDecodeRow(&gGIFData); else DoDecodeDummyRow(&gGIFData); SwapMMUMode(&mmuMode); return gGIFData.theReturn; } #if !USE_ASM //===================================================================================== // Generic C substitutes for the assembly functions defined below. //===================================================================================== static void DoDecodeRow(GIFDataPtr theData) { #include "DecodeRow.c" } static void DoDecodeDummyRow(GIFDataPtr theData) { #include "DecodeDummyRow.c" } #elif THINK_C //===================================================================================== // Assembly language interfaces for THINK C; here we define the offsets of all fields // within the GIFData structure, and then provide C function wrappers around asm { } // statements that #include the actual assembly code. In MPW, we just need to compile // GIF.a to get the assembly routines. //===================================================================================== #define src offsetof(GIFData, src) /* 0 */ #define dest offsetof(GIFData, dest) /* 4 */ #define stack offsetof(GIFData, stack) /* 8 */ #define theEnd offsetof(GIFData, end) /* 12 */ #define tree offsetof(GIFData, tree) /* 16 */ #define store offsetof(GIFData, store) /* 20 */ #define charSize offsetof(GIFData, charSize) /* 68 */ #define width offsetof(GIFData, width) /* 70 */ #define theReturn offsetof(GIFData, theReturn) /* 72 */ static void DoDecodeRow(GIFDataPtr theData) { asm { #include "DecodeRow.a" } } static void DoDecodeDummyRow(GIFDataPtr theData) { asm { #include "DecodeDummyRow.a" } } #endif \ No newline at end of file diff --git a/Source/C/GeneralMenus.c b/Source/C/GeneralMenus.c new file mode 100644 index 0000000..82b245c --- /dev/null +++ b/Source/C/GeneralMenus.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local variables: * lFileMenu = handle to the File menu * lEditMenu = handle to the Edit menu * lViewMenu = handle to the View menu * lColorMenu = handle to the Colors menu * lWindowMenu = handle to the Window menu * lHelpMenu = handle to the help menu * lMenuPalette = handle to the palette used when saving the window contents * lMenuGWorld = pointer to the GWorld to CopyBits() into * lMenuDither = flag: true if we dithered the image under the menu bar * lMenuimage = pointer to the image whose contents are saved in lMenuGWorld * */ static MenuHandle gFileMenu, gEditMenu, gViewMenu, gColorMenu, gWindowMenu, gHelpMenu, gQualityMenu; static PaletteHandle gMenuPalette = nil; static GWorldPtr gMenuGWorld = nil; static Boolean gMenuDither = false; static ImageHandle gMenuImage = nil; static short gMenuDepth = 32; static Rect gMenuRect; /* * MenuBarInit() * * Purpose: Loads the menu resources, installs the help item, and gets handles to * all the menus * Inputs: none * Returns: nothing * */ void MenuBarInit(void) { Handle theMenuBar; RgnHandle theRgn; FSSpec theSpec; Rect theRect; if (theRgn = GetMenuRgn()) { theRect = (*theRgn)->rgnBBox; if (!(gMenuGWorld = MyNewGWorld(&theRect, 32, nil, nil, false, false))) FatalError(errNoMemory); } else FatalError(errNoMemory); if ((theMenuBar = GetNewMBar(rMenuBar)) == nil) FatalError(errNoMenu); SetMenuBar(theMenuBar); if ((gQualityMenu = GetMenu(rQualityMenu)) == nil) FatalError(errNoMenu); InsertMenu(gQualityMenu, hierMenu); if ((gAppleMenu = GetMHandle(rAppleMenu)) == nil) FatalError(errNoMenu); AddResMenu(gAppleMenu, 'DRVR'); if ((gFileMenu = GetMHandle(rFileMenu)) == nil) FatalError(errNoMenu); if ((gEditMenu = GetMHandle(rEditMenu)) == nil) FatalError(errNoMenu); if ((gViewMenu = GetMHandle(rViewMenu)) == nil) FatalError(errNoMenu); if ((gColorMenu = GetMHandle(rColorsMenu)) == nil) FatalError(errNoMenu); if ((gWindowMenu = GetMHandle(rWindowMenu)) == nil) FatalError(errNoMenu); if (HMGetHelpMenuHandle(&gHelpMenu) != noErr) gHelpMenu = nil; if (gHelpMenu) { gHelpItem = CountMItems(gHelpMenu); InsMenuItem(gHelpMenu, gString[strJPEGViewHelp], gHelpItem++); SetItemCmd(gHelpMenu, gHelpItem, '?'); } DrawMenuBar(); gSlideFolderValid = (GetSlideSpec(&theSpec) == noErr); KeepSpinning(); } extern long MakeMenuSelection(short menu, short item) { return ((long)menu << 16) + item; } /* * HandleMenuChoice(theChoice) * * Purpose: Handles menu selection and dispatches to the proper menu handler * Inputs: theChoice = the menu selection, where the high word is the menu ID and * the low word is the item number * Returns: nothing * */ void HandleMenuChoice(long theChoice) { short item = theChoice & 0xffff, menu = (ulong)theChoice >> 16; ImageHandle theImage; theImage = FrontImage(); if (theImage && Full(theImage) && ((*theImage)->dmon == gMainMonitor) && gMenuVisible && gSlideShow != kPaused) { RehideMenuBar(); ActivateAnts((*theImage)->ants); } switch (menu) { case rAppleMenu: HandleAppleChoice(item); break; case rFileMenu: HandleFileChoice(item); break; case rEditMenu: HandleEditChoice(item); break; case rViewMenu: HandleViewChoice(item); break; case rColorsMenu: HandleColorChoice(item); break; case rQualityMenu: HandleQualityChoice(item); break; case rWindowMenu: HandleWindowChoice(item); break; case kHMHelpMenuID: HandleHelpChoice(item); break; } SetStatistics(); if (!gDone) { MySetPort(nil); HiliteMenu(0); } } /* * SaveMenuArea() * * Purpose: Saves the area behind the menubar in the offscreen GWorld * Inputs: none * Returns: nothing * */ void SaveMenuArea(void) { RgnHandle menuRgn = GetMenuRgn(); Rect menuRect = (*menuRgn)->rgnBBox; PixMapHandle src, dst; WindowPtr theWindow; char sState, dState, pState; ImageHandle theImage; Boolean newGWorld = false; if (theWindow = FWFrontWindow()) { if (theImage = FindImage(theWindow)) { if (gMenuGWorld) { PushPort(); MySetPort(gMenuGWorld); sState = HGetState((Handle)(src = GetGWorldPixMap((GWorldPtr)theWindow))); dState = HGetState((Handle)(dst = GetGWorldPixMap(gMenuGWorld))); pState = GetPixelsState(dst); HLock((Handle)src); HLock((Handle)dst); LockPixels(dst); RGBForeColor(&gBlack); RGBBackColor(&gWhite); HideCursor(); CopyBits((BitMap *)*src, (BitMap *)*dst, &menuRect, &menuRect, srcCopy, nil); ShowCursor(); SetPixelsState(dst, pState); HSetState((Handle)dst, dState); HSetState((Handle)src, sState); gMenuImage = theImage; gMenuDither = Dithered(theImage); gMenuPalette = (*theImage)->palette; gMenuRect = (*theImage)->wrect; gMenuDepth = (*(*(*gMainMonitor)->device)->gdPMap)->pixelSize; PopPort(); return; } } } gMenuImage = nil; } /* * RestoreMenuArea() * * Purpose: Restores the area behind the menubar in the offscreen GWorld * Inputs: none * Returns: nothing * */ void RestoreMenuArea(void) { RgnHandle menuRgn = GetMenuRgn(); Rect menuRect = (*menuRgn)->rgnBBox; PixMapHandle src, dst; ImageHandle theImage; WindowPtr theWindow; char sState, dState, pState; if (!gMenuGWorld) return; if (theWindow = FWFrontWindow()) { if (theWindow && gMenuImage && (theImage = FindImage(theWindow)) == gMenuImage) { if (Dithered(theImage) == gMenuDither && (*theImage)->palette == gMenuPalette && (*(*(*gMainMonitor)->device)->gdPMap)->pixelSize == gMenuDepth && EqualSizeRect(&(*theImage)->wrect, &gMenuRect)) { PushPort(); MySetPort((CGrafPtr)theWindow); ClipRect(&menuRect); sState = HGetState((Handle)(src = GetGWorldPixMap(gMenuGWorld))); dState = HGetState((Handle)(dst = GetGWorldPixMap((GWorldPtr)theWindow))); pState = GetPixelsState(src); HLock((Handle)src); HLock((Handle)dst); LockPixels(src); RGBForeColor(&gBlack); RGBBackColor(&gWhite); HideCursor(); CopyBits((BitMap *)*src, (BitMap *)*dst, &menuRect, &menuRect, srcCopy, nil); ShowCursor(); SetPixelsState(src, pState); HSetState((Handle)dst, dState); HSetState((Handle)src, sState); ValidRect(&menuRect); PopPort(); return; } } } } /* * DisableMenus() * * Purpose: Disables all the menu titles * Inputs: none * Returns: nothing * */ void DisableMenus(void) { DisableItem(gAppleMenu, 0); DisableItem(gFileMenu, 0); DisableItem(gEditMenu, 0); DisableItem(gViewMenu, 0); DisableItem(gColorMenu, 0); DisableItem(gWindowMenu, 0); gMenuEnabled = false; if (gMenuVisible) { PushPort(); MySetPort(nil); MyInvalMenuBar(); PopPort(); } } /* * EnableMenus() * * Purpose: Enables all appropriate menu titles * Inputs: none * Returns: nothing * */ void EnableMenus(void) { EnableItem(gAppleMenu, 0); EnableItem(gFileMenu, 0); if (FrontImage()) { EnableItem(gEditMenu, CanSelectScreen()); EnableItem(gViewMenu, 0); EnableItem(gColorMenu, 0); } EnableItem(gWindowMenu, 0); MyInvalMenuBar(); gMenuEnabled = true; } /* * AdjustMenus() * * Purpose: Adjusts the menus to reflect the current program status * Inputs: none * Returns: nothing * */ void AdjustMenus(void) { short var; var = FWFrontWindow() ? GetWVariant(FWFrontWindow()) : 0; MenuEnable(gAppleMenu, 0, var != dBoxProc); MenuEnable(gAppleMenu, appleAboutItem, var != movableDBoxProc && !gDrawing && !gSlideShow); MenuEnable(gAppleMenu, appleAboutHelpItem, var != movableDBoxProc && !gDrawing && !gSlideShow); AdjustFile(var); AdjustEdit(var); AdjustView(var); AdjustColor(var); AdjustWindow(var); if (gHelpMenu) MenuEnable(gHelpMenu, gHelpItem, var != movableDBoxProc && !gDrawing && gSlideShow != kRunning); if (LMGetTheMenu()) MyInvalMenuBar(); else DrawMenuBar(); } /* * AdjustFile(var) * * Purpose: Adjusts the File menu to reflect the current program status * Inputs: var = the window type so we can enable/disable for dialogs * Returns: nothing * */ void AdjustFile(short var) { WindowPtr frontWindow = FWFrontWindow(); ImageHandle theImage = FrontImage(); MenuEnable(gFileMenu, 0, var != dBoxProc && var != movableDBoxProc && !gDrawing); if (gSlideShow) { DisableItem(gFileMenu, fileOpenItem); DisableItem(gFileMenu, fileImportItem); MenuEnable(gFileMenu, fileCloseItem, frontWindow && frontWindow != GetSlideBackWindow() && !theImage); DisableItem(gFileMenu, fileCloseAllItem); DisableItem(gFileMenu, fileSaveItem); DisableItem(gFileMenu, filePageSetupItem); DisableItem(gFileMenu, filePrintItem); SetItem(gFileMenu, fileStartSlideItem, gString[strResumeSlideShow]); MenuEnable(gFileMenu, fileStartSlideItem, gSlideShow == kPaused); EnableItem(gFileMenu, fileEndSlideItem); } else { EnableItem(gFileMenu, fileOpenItem); EnableItem(gFileMenu, fileImportItem); MenuEnable(gFileMenu, fileCloseItem, frontWindow); MenuEnable(gFileMenu, fileCloseAllItem, gImageRoot); MenuEnable(gFileMenu, fileSaveItem, theImage);// && !Cropped(theImage)); SetItem(gFileMenu, fileStartSlideItem, gString[strBeginSlideShow]); MenuEnable(gFileMenu, fileStartSlideItem, ((*gSlideOptions)->fromMemory && gImageRoot) || (!(*gSlideOptions)->fromMemory && gSlideFolderValid)); DisableItem(gFileMenu, fileEndSlideItem); EnableItem(gFileMenu, filePageSetupItem); MenuEnable(gFileMenu, filePrintItem, theImage); EnableItem(gFileMenu, fileQuitItem); } } /* * AdjustEdit(var) * * Purpose: Adjusts the Edit menu to reflect the current program status * Inputs: var = the window type so we can enable/disable for dialogs * Returns: nothing * */ void AdjustEdit(short var) { #if applec #pragma unused(var) #endif WindowPtr frontWindow = FWFrontWindow(); ImageHandle theImage = FrontImage(); Boolean dialog = (frontWindow && WindowKind(frontWindow) == dialogKind); Boolean enable = theImage && !gSlideShow && CanSelectScreen(); long dialogID = 0; if (frontWindow) var = GetWVariant(frontWindow); if (dialog) dialogID = GetWRefCon(frontWindow); if (dialog && (dialogID != kSlideShowDialogID || (*gSlideOptions)->userControl)) { MenuEnable(gEditMenu, 0, false); return; } if (gDrawing || gSlideShow == kRunning) { MenuEnable(gEditMenu, 0, false); return; } MenuEnable(gEditMenu, 0, dialog || theImage); MenuEnable(gEditMenu, editUndoItem, false); MenuEnable(gEditMenu, editCutItem, dialog); MenuEnable(gEditMenu, editCopyItem, dialog || theImage); MenuEnable(gEditMenu, editPasteItem, dialog); MenuEnable(gEditMenu, editClearItem, dialog); MenuEnable(gEditMenu, editSelectScreenItem, enable); MenuEnable(gEditMenu, editCropItem, !gSlideShow && theImage && !IsAboutBox(theImage) && AntsHaveSelection((*theImage)->ants)); MenuEnable(gEditMenu, editUncropItem, !gSlideShow && theImage && Cropped(theImage) && !Banded(theImage)); } /* * CanSelectScreen() * * Purpose: Determines if we should allow select screen area * Inputs: none * Returns: true if we're allowed to select the screen area; false otherwise * */ Boolean CanSelectScreen(void) { ImageHandle theImage = FrontImage(); Rect theRect; if (!theImage) return false; GetActiveRect((*theImage)->dmon, &theRect); if (!Full(theImage)) theRect.top += gTitleBarHeight; return (Width(&(*theImage)->crect) > Width(&theRect)) || (Height(&(*theImage)->crect) > Height(&theRect)); } /* * AdjustView(var) * * Purpose: Adjusts the View menu to reflect the current program status * Inputs: var = the window type so we can enable/disable for dialogs * Returns: nothing * */ void AdjustView(short var) { #if applec #pragma unused(var) #endif ImageHandle theImage = FrontImage(); Rect theRect; if (theImage) { GetActiveRect((*theImage)->dmon, &theRect); if (!Full(theImage)) theRect.top += gTitleBarHeight; } MenuEnable(gViewMenu, 0, !gSlideShow && !gDrawing && theImage && theImage == FrontImage()); CheckItem(gViewMenu, viewFullScreenItem, theImage && Full(theImage)); MenuEnable(gViewMenu, viewNormalItem, theImage && !EqualSizeRect(&(*theImage)->wrect, &(*theImage)->crect)); MenuEnable(gViewMenu, viewHalfItem, theImage && !IsAboutBox(theImage) && (Width(&(*theImage)->wrect) > 64) && (Height(&(*theImage)->wrect) > 64)); MenuEnable(gViewMenu, viewDoubleItem, theImage && !IsAboutBox(theImage) && ((Width(&(*theImage)->wrect) << 1) <= Width(&theRect)) && ((Height(&(*theImage)->wrect) << 1) <= Height(&theRect))); MenuEnable(gViewMenu, viewMaxItem, theImage && !IsAboutBox(theImage) && (Width(&(*theImage)->wrect) != Width(&theRect)) && (Height(&(*theImage)->wrect) != Height(&theRect))); MenuEnable(gViewMenu, viewShrinkItem, theImage && !IsAboutBox(theImage) && (Width(&(*theImage)->wrect) > 36) && (Height(&(*theImage)->wrect) > 36)); MenuEnable(gViewMenu, viewExpandItem, theImage && !IsAboutBox(theImage) && ((11 * Width(&(*theImage)->wrect) / 10) <= Width(&theRect)) && ((11 * Height(&(*theImage)->wrect) / 10) <= Height(&theRect))); } /* * AdjustColor(var) * * Purpose: Adjusts the Color menu to reflect the current program status * Inputs: var = the window type so we can enable/disable for dialogs * Returns: nothing * */ void AdjustColor(short var) { #if applec #pragma unused(var) #endif short mdepth = 0, depth = 0, palette; ImageHandle theImage = FrontImage(); Boolean enabled; if (!gSlideShow && !gDrawing && theImage && (*theImage)->smon && (*theImage)->dmon) { EnableItem(gColorMenu, 0); mdepth = (*(*theImage)->smon)->depth; depth = (*(*theImage)->dmon)->depth; palette = (*theImage)->npalette; enabled = (depth >= 4); MenuEnable(gColorMenu, colorSysItem, enabled); CheckItem(gColorMenu, colorSysItem, enabled && (palette == plSys)); enabled = (mdepth <= 8); MenuEnable(gColorMenu, colorGrayItem, enabled); CheckItem(gColorMenu, colorGrayItem, enabled && (palette == plGrey)); enabled = ((*theImage)->ipalette != nil) && (depth >= 4) && (mdepth <= 8) && ((*(*theImage)->ipalette)->pmEntries <= (1L << depth)); MenuEnable(gColorMenu, colorImageItem, enabled); CheckItem(gColorMenu, colorImageItem, enabled && (palette == plImage)); enabled = (depth >= 4) && (mdepth <= 8) && ((*theImage)->depth >= 16); MenuEnable(gColorMenu, colorQuantItem, enabled); CheckItem(gColorMenu, colorQuantItem, enabled && (palette == plQuant)); enabled = (depth <= 16); MenuEnable(gColorMenu, colorDitherItem, enabled); CheckItem(gColorMenu, colorDitherItem, enabled && Dithered(theImage)); enabled = ((*theImage)->depth >= 24) && ((depth > 8) || ((depth == 8) && ((*theImage)->npalette != plSys) && ((*theImage)->npalette != plGrey))); MenuEnable(gColorMenu, colorQualityItem, enabled); MenuEnable(gQualityMenu, 0, enabled); CheckItem(gQualityMenu, qualityVHighItem, enabled && ((*theImage)->quality == iqVHigh)); MenuEnable(gQualityMenu, qualityHighItem, enabled && (depth < 24)); CheckItem(gQualityMenu, qualityHighItem, enabled && (depth < 24) && ((*theImage)->quality == iqHigh)); CheckItem(gQualityMenu, qualityMediumItem, enabled && ((*theImage)->quality == iqMedium) || (((*theImage)->quality == iqHigh) && (depth >= 24))); } else { CheckItem(gColorMenu, colorSysItem, false); CheckItem(gColorMenu, colorGrayItem, false); CheckItem(gColorMenu, colorImageItem, false); CheckItem(gColorMenu, colorQuantItem, false); CheckItem(gColorMenu, colorDitherItem, false); DisableItem(gColorMenu, 0); } } /* * AdjustWindow(var) * * Purpose: Adjusts the Window menu to reflect the current program status * Inputs: var = the window type so we can enable/disable for dialogs * Returns: nothing * */ void AdjustWindow(short var) { ImageHandle theImage; short theItem; MenuEnable(gWindowMenu, 0, var != dBoxProc && var != movableDBoxProc && !gDrawing); MenuEnable(gWindowMenu, windowStatItem, true); MenuEnable(gWindowMenu, windowCommentsItem, true); MenuEnable(gWindowMenu, windowPreviousItem, !gSlideShow && gImageRoot && (*gImageRoot)->next); MenuEnable(gWindowMenu, windowNextItem, !gSlideShow && gImageRoot && (*gImageRoot)->next); for (theImage = gImageRoot, theItem = windowFirstItem; theImage; theImage = (*theImage)->next, theItem++) { CheckItem(gWindowMenu, theItem, (*theImage)->window == FWFrontWindow()); MenuEnable(gWindowMenu, theItem, !gSlideShow); } if (GetStatWindow()) SetItem(gWindowMenu, windowStatItem, gString[strHideStatistics]); else SetItem(gWindowMenu, windowStatItem, gString[strShowStatistics]); if (GetCommentsWindow()) SetItem(gWindowMenu, windowCommentsItem, gString[strHideComments]); else SetItem(gWindowMenu, windowCommentsItem, gString[strShowComments]); if (GetColorsWindow()) SetItem(gWindowMenu, windowColorsItem, gString[strHideColors]); else SetItem(gWindowMenu, windowColorsItem, gString[strShowColors]); theImage = FrontImage(); if (theImage && (*theImage)->comments) SetItemMark(gWindowMenu, windowCommentsItem, diamondMark); else SetItemMark(gWindowMenu, windowCommentsItem, noMark); } /* * AddWindowItem(theImage) * * Purpose: Adds the name of theImage to the bottom of the Window menu * Inputs: none * Returns: nothing * */ void AddWindowItem(ImageHandle theImage) { int item = GetDocumentIndex((*theImage)->window) + windowFirstItem - 1; Str255 theItem; if (gImageRoot == theImage && !(*theImage)->next) AppendMenu(gWindowMenu, (StringPtr)"\p(-"); AppendMenu(gWindowMenu, (StringPtr)"\p "); BlockMove((*theImage)->file.name, theItem, 64); if ((*theImage)->num) { AddChar(theItem, ' '); AddNumber(theItem, (*theImage)->num); } SetItem(gWindowMenu, item, theItem); if (item < (9 + windowFirstItem)) SetItemCmd(gWindowMenu, item, item - windowFirstItem + '1'); } /* * DeleteWindowItem(theImage) * * Purpose: Removes the name of theImage from the Window menu * Inputs: none * Returns: nothing * */ void DeleteWindowItem(ImageHandle theImage) { int item = GetDocumentIndex((*theImage)->window) + windowFirstItem - 1; ImageHandle image; if (item > CountMItems(gWindowMenu)) return; DelMenuItem(gWindowMenu, item); for (item = windowFirstItem, image = gImageRoot; image; image = (*image)->next) if (image != theImage && item < (9 + windowFirstItem)) { SetItemCmd(gWindowMenu, item, item - windowFirstItem + '1'); item++; } if (gImageRoot == theImage && !(*theImage)->next) DelMenuItem(gWindowMenu, windowFirstItem - 1); } \ No newline at end of file diff --git a/Source/C/HelpMenu.c b/Source/C/HelpMenu.c new file mode 100644 index 0000000..4772eee --- /dev/null +++ b/Source/C/HelpMenu.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local variables: * lHelpScroll = handle to the scroll bar * lHelpTextEdit = TextEdit record for the help window * lHelpWindow = pointer to the dialog record for the help dialog * */ static ControlHandle gHelpScroll = nil, gHelpMenu = nil; static Rect gHelpTextRect = { 34, 9, 287, 459 }; static TEHandle gHelpTextEdit = nil; static WindowPtr gHelpWindow = nil; static ControlActionUPP gHelpScrollAction = nil; extern void HandleHelpGrow(Point where) { Rect limitRect = { 150, 400, 32767, 32767 }, newRect; long newSize; if (newSize = GrowWindow(gHelpWindow, where, &limitRect)) { newRect = gHelpWindow->portRect; newRect.right = newRect.left + (newSize & 0xffff); newRect.bottom = newRect.top + (newSize >> 16); GlobalRect(&newRect, gHelpWindow); SendSetWindowBounds(gHelpWindow, &newRect); } } /* * HandleHelpChoice(theItem) * * Purpose: Handles menu events from the Help menu * Inputs: theItem = the menu item number * Returns: nothing * */ void HandleHelpChoice(short theItem) { if (theItem == gHelpItem) SendCreateWindow(kHelpWindowID); } /* * OpenHelp() * * Purpose: Creates and initializes the help dialog and its various controls * Inputs: theSection = the section to open up to * Returns: nothing * */ OSErr OpenHelp(void) { OSErr theErr = noErr; Point where; if (!gHelpFound) return errNoHelpFound; if (gHelpWindow) { if (!WindowVisible(gHelpWindow)) FWShowWindow(gHelpWindow); return noErr; } StartSpinning(); if (!(gHelpWindow = AllocateWindow())) return memFullErr; KeepSpinning(); PushPort(); MySetPort(nil); if (gHelpWindow = FWGetNewWindow(rHelpWindow, (Ptr)gHelpWindow, (WindowPtr)-1)) { MySetPort((CGrafPtr)gHelpWindow); KeepSpinning(); if ((gHelpTextEdit = TEStylNew(&gHelpTextRect, &gHelpTextRect)) && (gHelpScroll = GetNewControl(rHelpScrollControl, gHelpWindow)) && (gHelpMenu = GetNewControl(rHelpMenuControl, gHelpWindow))) { KeepSpinning(); SetCtlValue(gHelpMenu, gThePrefs.helpSection); GetHelpText(gThePrefs.helpSection - 1); if (gHelpWindow) { if ((gThePrefs.helpBounds.top == gThePrefs.helpBounds.bottom) || (DoSetWindowBounds(gHelpWindow, &gThePrefs.helpBounds) != noErr)) { where = CenterWindow(gHelpWindow); FWMoveWindow(gHelpWindow, where.h, where.v, false); } ResizeHelp(&gHelpWindow->portRect); } StopSpinning(&qd.arrow); PopPort(); return noErr; } else gIntError = errNoHelp, theErr = memFullErr; } else gIntError = errNoHelp, theErr = memFullErr; CloseHelp(); StopSpinning(&qd.arrow); PopPort(); return theErr; } /* * CloseHelp() * * Purpose: Creates and initializes the help dialog and its various controls * Inputs: theSection = the section to open up to * Returns: nothing * */ void CloseHelp(void) { PushPort(); MySetPort(nil); if (gHelpScroll) DisposeControl(gHelpScroll); gHelpScroll = nil; if (gHelpMenu) DisposeControl(gHelpMenu); gHelpMenu = nil; if (gHelpTextEdit) TEDispose(gHelpTextEdit); gHelpTextEdit = nil; if (gHelpWindow) { SaveWindowPosition(gHelpWindow, &gThePrefs.helpBounds); FWCloseWindow(gHelpWindow); DeallocateWindow(gHelpWindow); } gHelpWindow = nil; PopPort(); } /* * GetHelpWindow() * * Purpose: Returns a pointer to the help window * Inputs: none * Returns: nothing * */ WindowPtr GetHelpWindow(void) { return gHelpWindow; } /* * HandleHelpClick(theItem) * * Purpose: Handles events in the help dialog * Inputs: theItem = the item that was clicked on * Returns: nothing * */ void HandleHelpClick(Point where) { ControlHandle theControl; short thePart, theValue; MySetPort((CGrafPtr)gHelpWindow); GlobalToLocal(&where); if (!(thePart = FindControl(where, gHelpWindow, &theControl))) return; if (theControl == gHelpScroll) { if (thePart == inThumb) { theValue = GetCtlValue(theControl); if (TrackControl(theControl, where, nil)) UpdateHelpScroll(theValue, GetCtlValue(theControl)); } else { if (!gHelpScrollAction) gHelpScrollAction = NewControlActionProc((ProcPtr)HelpScrollAction); TrackControl(theControl, where, gHelpScrollAction); } } else if (theControl == gHelpMenu) { if (TrackControl(theControl, where, (ControlActionUPP)-1)) { gThePrefs.helpSection = GetCtlValue(theControl); GetHelpText(gThePrefs.helpSection - 1); } } } /* * HandleHelpKey(theChar, theKey) * * Purpose: Handles key down events in the help window * Inputs: theChar = the ASCII representation of the character * theKey = the key code of the key pressed * Returns: nothing * */ Boolean HandleHelpKey(uchar theChar, uchar theKey) { #if applec #pragma unused(theKey) #endif Boolean result = false; PushPort(); MySetPort((CGrafPtr)gHelpWindow); switch (theChar) { case kPageUpChar: HelpScrollAction(gHelpScroll, inPageUp); result = true; break; case kPageDownChar: HelpScrollAction(gHelpScroll, inPageDown); result = true; break; } PopPort(); return result; } /* * HandleHelpActivate(nowActive) * * Purpose: Handles activate/deactivate events in the help window * Inputs: nowActive = flag: true if we're now becoming the active window * Returns: nothing * */ void HandleHelpActivate(Boolean nowActive) { Rect theRect; PushPort(); MySetPort((CGrafPtr)gHelpWindow); ClipRect(&gHelpWindow->portRect); if (gHelpScroll) { if (nowActive) ShowControl(gHelpScroll); else { HideControl(gHelpScroll); MoveTo((*gHelpScroll)->contrlRect.left, (*gHelpScroll)->contrlRect.top); LineTo((*gHelpScroll)->contrlRect.right, (*gHelpScroll)->contrlRect.top); } } theRect = gHelpWindow->portRect; theRect.left = theRect.right - 15; theRect.top = gHelpTextRect.top - 1; ClipRect(&theRect); DrawGrowIcon(gHelpWindow); ClipRect(&gHelpWindow->portRect); PopPort(); } /* * GetHelpText(theSect) * * Purpose: Fetches the desired text from its resource, copies it into the TextEdit * record, and resets the scroll bar maximum * Inputs: theSect = the section number we're interested in * Returns: nothing * */ void GetHelpText(short theSect) { Handle helpText, helpStyl; if (helpText = GetCompResource('ctxt', kHelpTextBase + theSect)) { if (helpStyl = GetCompResource('csty', kHelpTextBase + theSect)) { TESetSelect(0, 32767, gHelpTextEdit); TEDelete(gHelpTextEdit); HLock(helpText); HLock(helpStyl); TEScroll(0, (*gHelpTextEdit)->viewRect.top - (*gHelpTextEdit)->destRect.top, gHelpTextEdit); TEStylInsert(*helpText, GetHandleSize(helpText), (StScrpHandle)helpStyl, gHelpTextEdit); HUnlock(helpStyl); HUnlock(helpText); ReleaseResource(helpText); ReleaseResource(helpStyl); ResizeHelp(&gHelpWindow->portRect); return; } } MinorError(errNoHelp); CloseHelp(); } /* * ResizeHelp(newRect) * * Purpose: Redraws the help window * Inputs: newRect = pointer to the new window rectangle * Returns: nothing * */ void ResizeHelp(Rect *newRect) { Rect itemRect = *newRect, menuRect, monRect, oldRect = gHelpWindow->portRect; MonitorHandle largeMon = GetBigMonitor(false); short theMax, theAmount = 0; LHHandle theLines; GetActiveRect(largeMon, &monRect); monRect.top += gTitleBarHeight; if (Width(newRect) > Width(&monRect)) newRect->right = newRect->left + (Width(&monRect) - 2 * kWindowBorderWidth); if (Height(newRect) > Height(&monRect)) newRect->bottom = newRect->top + (Height(&monRect) - 2 * kWindowBorderHeight); SizeWindow(gHelpWindow, Width(newRect), Height(newRect), false); OffsetRect(&itemRect, -itemRect.left, -itemRect.top); PushPort(); MySetPort((CGrafPtr)gHelpWindow); ClipRect(&gHelpWindow->portRect); if (gHelpTextEdit) { InsetRect(&itemRect, 1, 1); itemRect.top += 10 + 20 + 6; itemRect.right -= 15; gHelpTextRect = (*gHelpTextEdit)->viewRect = (*gHelpTextEdit)->destRect = itemRect; TECalText(gHelpTextEdit); theLines = (*GetStylHandle(gHelpTextEdit))->lhTab; theMax = (*gHelpTextEdit)->nLines + 1; while ((theMax > 0) && (theAmount < Height(&gHelpTextRect))) { theMax--; theAmount += (*theLines)[theMax].lhHeight; } } if (gHelpScroll) { MoveControl(gHelpScroll, itemRect.right + 1, itemRect.top - 2); SizeControl(gHelpScroll, Width(&(*gHelpScroll)->contrlRect), Height(&itemRect) + 4 - 15); SetCtlMax(gHelpScroll, theMax); SetCtlValue(gHelpScroll, 0); } if (gHelpMenu) { menuRect = (*gHelpMenu)->contrlRect; MoveControl(gHelpMenu, (Width(&itemRect) - Width(&menuRect)) >> 1, menuRect.top); } itemRect = gHelpWindow->portRect; itemRect.top = gHelpTextRect.top - 2; if (!EqualSizeRect(&oldRect, newRect)) InvalRect(&itemRect); PopPort(); } /* * UpdateHelp() * * Purpose: Redraws the help window * Inputs: none * Returns: nothing * */ void UpdateHelp(void) { Rect theRect; TextFont(systemFont); TextSize(12); ClipRect(&gHelpWindow->portRect); PenSize(1, 1); InsetRect(&gHelpTextRect, -1, -1); PenPat(&qd.white); FrameRect(&gHelpTextRect); InsetRect(&gHelpTextRect, -1, -1); PenPat(&qd.black); FrameRect(&gHelpTextRect); InsetRect(&gHelpTextRect, 2, 2); MoveTo((*gHelpScroll)->contrlRect.left, (*gHelpScroll)->contrlRect.top); LineTo((*gHelpScroll)->contrlRect.right, (*gHelpScroll)->contrlRect.top); TEUpdate(&gHelpTextRect, gHelpTextEdit); UpdtControl(gHelpWindow, gHelpWindow->visRgn); theRect = gHelpWindow->portRect; theRect.left = theRect.right - 15; theRect.top = gHelpTextRect.top - 1; ClipRect(&theRect); DrawGrowIcon(gHelpWindow); ClipRect(&gHelpWindow->portRect); } /* * UpdateHelpScroll(oldValue, newValue) * * Purpose: Updates the scroll bars to the newValue from oldValue * Inputs: oldValue = the previous position of the scroll bar * newValue = the new position of the scroll bar * Returns: nothing * */ void UpdateHelpScroll(short oldValue, short newValue) { LHHandle theLines = (*GetStylHandle(gHelpTextEdit))->lhTab; short theAmount = 0; if (newValue < oldValue) { while (oldValue != newValue) { oldValue--; theAmount += (*theLines)[oldValue].lhHeight; } } else { while (oldValue != newValue) { theAmount -= (*theLines)[oldValue].lhHeight; oldValue++; } } if (theAmount) TEScroll(0, theAmount, gHelpTextEdit); } /* * HelpScrollAction(theControl, thePart) * * Purpose: Called by TrackControl() to constantly update the scrolling region while * the mouse button is held down * Inputs: theControl = handle of the scroll bar * thePart = the part that's being clicked on * Returns: nothing * */ pascal void HelpScrollAction(ControlHandle theControl, short thePart) { short theAmount = 0, theValue, maxValue; LHHandle theLines; if (!thePart) return; theLines = (*GetStylHandle(gHelpTextEdit))->lhTab; theValue = GetCtlValue(theControl); maxValue = GetCtlMax(theControl); switch (thePart) { case inUpButton: if (theValue > 0) { theValue--; theAmount = (*theLines)[theValue].lhHeight; } break; case inDownButton: if (theValue < maxValue) { theAmount = -(*theLines)[theValue].lhHeight; theValue++; } break; case inPageUp: while ((theValue > 0) && (theAmount < (Height(&(*gHelpTextEdit)->viewRect) - 10))) { theValue--; theAmount += (*theLines)[theValue].lhHeight; } break; case inPageDown: while ((theValue < maxValue) && (-theAmount < (Height(&(*gHelpTextEdit)->viewRect) - 10))) { theAmount -= (*theLines)[theValue].lhHeight; theValue++; } break; } SetCtlValue(theControl, theValue); if (theAmount) TEScroll(0, theAmount, gHelpTextEdit); } /* * DoHelpHelp(globalPt) * * Purpose: Pops up help for the help window; needed because things keep moving around * Inputs: globalPt = point, in global coordinates, where the mouse is * Returns: nothing * */ void DoHelpHelp(Point globalPt) { Point tip = { 0, 0 }, localPt = globalPt; HMMessageRecord theRecord; short index = 0; Rect aRect; if (HMIsBalloon() || gInBackground) return; PushPort(); MySetPort((CGrafPtr)gHelpWindow); GlobalToLocal(&localPt); if (localPt.h >= (gHelpWindow->portRect.right - 15) && localPt.v >= (gHelpWindow->portRect.bottom - 15)) { aRect = gHelpWindow->portRect; aRect.top = aRect.bottom - 15; aRect.left = aRect.right - 15; tip.h = aRect.left + (Width(&aRect) >> 1); tip.v = aRect.top + (Height(&aRect) >> 1); index = 1; } else if (PtInRect(localPt, &(*gHelpScroll)->contrlRect)) { aRect = (*gHelpScroll)->contrlRect; tip.h = aRect.left + (Width(&aRect) >> 1); tip.v = aRect.top + (Height(&aRect) >> 1); index = 2; } else if (PtInRect(localPt, &(*gHelpMenu)->contrlRect)) { aRect = (*gHelpMenu)->contrlRect; tip = BotRight(aRect); tip.h -= 10; tip.v -= 10; index = 3; } else if (PtInRect(localPt, &(*gHelpTextEdit)->viewRect)) { aRect = (*gHelpTextEdit)->viewRect; tip = BotRight(aRect); tip.h -= 10; tip.v -= 10; index = 4; } if (index && HMExtractHelpMsg(kHMRectListResType, rHelpWindow, index, kHMEnabledItem, &theRecord) == noErr) { LocalToGlobal(&tip); GlobalRect(&aRect, gHelpWindow); HMShowBalloon(&theRecord, tip, &aRect, nil, 0, 0, kHMRegularWindow); } PopPort(); } \ No newline at end of file diff --git a/Source/C/IJGJPEG.c b/Source/C/IJGJPEG.c new file mode 100644 index 0000000..6946b00 --- /dev/null +++ b/Source/C/IJGJPEG.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #include #include "jpeglib.h" #include "jerror.h" static OSErr DecompressJPEGImage(struct jpeg_decompress_struct *cinfo, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog); static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow); GLOBAL void InitIJGSource (j_decompress_ptr cinfo, Handle theHandle); extern OSErr DrawJPEG(Handle theHandle, JVDrawParamsHandle theParams) { NestedProgress theProgress = (*theParams)->progress; struct jpeg_decompress_struct cinfo; char hState = HGetState(theHandle); struct jpeg_error_mgr jerr; GWorldPtr theGWorld; OSErr theErr; HLock(theHandle); cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); InitIJGSource(&cinfo, theHandle); jpeg_read_header(&cinfo, true); SysBeep(1); jpeg_start_decompress(&cinfo); SysBeep(1); /* { // note: need to set depth to 8 for grayscale images theGWorld = NewTempGWorld(cinfo.output_width, cinfo.output_height, (cinfo.out_color_components == 1) ? 40 : 32, nil); if (theGWorld) { theErr = DecompressJPEGImage(&cinfo, GetGWorldPixMap(theGWorld), (ICMProgressProcRecordPtr)&theProgress); if ((*theParams)->progress.aborted) theErr = codecAbortErr; DisposeGWorld(theGWorld); } else gIntError = errNoDrawMemory, theErr = memFullErr; }*/ SysBeep(1); jpeg_finish_decompress(&cinfo); SysBeep(1); jpeg_destroy_decompress(&cinfo); HSetState(theHandle, hState); return noErr; } static OSErr DecompressJPEGImage(struct jpeg_decompress_struct *cinfo, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog) { char pState = GetPixelsState(dstPixMap); RgnHandle dstRgn = qd.thePort->visRgn; ulong bandRow = 0, row, bufferRows = Height(&(*dstPixMap)->bounds); char mmuMode = true32b; OSErr theErr = noErr; uchar *rowStart; JSAMPARRAY scanLines; LockPixels(dstPixMap); rowStart = (uchar *)GetPixBaseAddr(dstPixMap); if (scanLines = (JSAMPARRAY)NewPtrClear(bufferRows * sizeof(JSAMPROW))) { for (row = 0; row < bufferRows; row++) scanLines[row] = rowStart, rowStart += (*dstPixMap)->rowBytes & 0x3fff; for (row = 0; row < cinfo->output_height; row += bufferRows) { SwapMMUMode(&mmuMode); jpeg_read_scanlines(cinfo, scanLines, bufferRows); SwapMMUMode(&mmuMode); CopyPixMapToDestination(dstPixMap, row); } /* for (row = 0; row < ; row++) { if (ptr < dataStart || ptr > dataEnd) { theErr = codecBadDataErr; break; } SwapMMUMode(&mmuMode); dst = rowStart; UnpackBits((Ptr *)&ptr, (Ptr *)&dst, 576 / 8); SwapMMUMode(&mmuMode); rowStart += ((*dstPixMap)->rowBytes & 0x3fff); if (!(row & 63) && prog->progressProc) theErr = (OSErr)CallICMProgressProc(prog->progressProc, codecProgressUpdatePercent, FixRatio(row, 720), prog->progressRefCon); if (++bandRow == Height(&(*dstPixMap)->bounds)) { CopyPixMapToDestination(dstPixMap, row - bandRow + 1); bandRow = 0; rowStart = (uchar *)GetPixBaseAddr(dstPixMap); } if (theErr != noErr) break; } if (theErr == noErr && bandRow) CopyPixMapToDestination(dstPixMap, row - bandRow);*/ } SetPixelsState(dstPixMap, pState); return theErr; } //===================================================================================== // void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) //===================================================================================== // Copies the band contained in srcPixMap to the destination, offset from the top by // startRow. //===================================================================================== static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) { Rect srcRect = (*srcPixMap)->bounds, dstRect = (*srcPixMap)->bounds; PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); char srcState = HGetState((Handle)srcPixMap); char dstState = HGetState((Handle)dstPixMap); OffsetRect(&dstRect, 0, startRow); HLock((Handle)srcPixMap); HLock((Handle)dstPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &srcRect, &dstRect, srcCopy + ditherCopy, qd.thePort->visRgn); HSetState((Handle)dstPixMap, dstState); HSetState((Handle)srcPixMap, srcState); } //============================================================================================ //============================================================================================ //=========================== ================================== //=========================== IJG Data Source Object Code ================================== //=========================== ================================== //============================================================================================ //============================================================================================ /* Expanded data source object for stdio input */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF void init_source (j_decompress_ptr cinfo) { } /* * Fill the input buffer --- called whenever buffer is emptied. */ METHODDEF boolean fill_input_buffer (j_decompress_ptr cinfo) { static JOCTET dummyBuffer[] = { (JOCTET)0xff, (JOCTET)JPEG_EOI }; my_src_ptr src = (my_src_ptr) cinfo->src; WARNMS(cinfo, JWRN_JPEG_EOF); src->pub.next_input_byte = (JOCTET *)&dummyBuffer; src->pub.bytes_in_buffer = 2; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). */ METHODDEF void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. */ METHODDEF void term_source (j_decompress_ptr cinfo) { } /* * Prepare for input from a memory handle. */ GLOBAL void InitIJGSource (j_decompress_ptr cinfo, Handle theHandle) { my_src_ptr src; /* The source object and input buffer are made permanent so that a series * of JPEG images can be read from the same file by calling jpeg_stdio_src * only before the first one. (If we discarded the buffer at the end of * one image, we'd likely lose the start of the next one.) * This makes it unsafe to use this manager and a different source * manager serially with the same JPEG object. Caveat programmer. */ if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr)); src = (my_src_ptr) cinfo->src; } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->pub.bytes_in_buffer = GetHandleSize(theHandle); src->pub.next_input_byte = (JOCTET *)StripAddress(*theHandle); } \ No newline at end of file diff --git a/Source/C/ImageUtils.c b/Source/C/ImageUtils.c new file mode 100644 index 0000000..6f325fd --- /dev/null +++ b/Source/C/ImageUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif static void HandleUpdateError(ImageHandle theImage, OSErr theErr); static void DoDragSelection(ImageHandle theImage, EventRecord *theEvent); static pascal OSErr SendItemData(FlavorType theType, void *dragSendRefCon, ItemReference theItem, DragReference theDrag); extern void DeferImageUpdate(ImageHandle theImage) { Pattern whitePat = { 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00 }; Pattern blackPat = { 0xff, 0xfd, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff }; RgnHandle theRgn; Rect theRect; PushPort(); MySetPort((CGrafPtr)(*theImage)->window); InvalRgn((*theImage)->update); BeginUpdate((*theImage)->window); PenNormal(); RGBForeColor(&gBlack); RGBBackColor(&gWhite); theRect = (*theImage)->wrect; if (theRgn = NewRgn()) { RectRgn(theRgn, &theRect); if (gDrawing && theImage == gDrawing) DiffRgn(theRgn, (*theImage)->update, theRgn); SetClip(theRgn); DisposeRgn(theRgn); } else ClipRect(&theRect); HideAnts((*theImage)->ants); FillRgn((*theImage)->window->visRgn, NeedsWhiteBG(theImage) ? &whitePat : &blackPat); ShowAnts((*theImage)->ants); ClipRect(&(*theImage)->window->portRect); UnionRgn((*theImage)->update, (*theImage)->window->visRgn, (*theImage)->update); EndUpdate((*theImage)->window); (*theImage)->flags &= ~ifAborted; PopPort(); } extern OSErr UpdateImage(ImageHandle theImage) { Point thePoint = { 0, 0 }; OSErr theErr = noErr; RgnHandle oldVisRgn; StartSpinning(); PushPort(); MySetPort((CGrafPtr)(*theImage)->window); if (oldVisRgn = NewRgn()) CopyRgn((*theImage)->window->visRgn, oldVisRgn); ClipRect(&(*theImage)->window->portRect); InvalRgn((*theImage)->update); BeginUpdate((*theImage)->window); SetClip((*theImage)->window->visRgn); EndUpdate((*theImage)->window); CopyRgn((*theImage)->window->clipRgn, (*theImage)->window->visRgn); GetMinMaxMonitor(theImage); gIntError = 0; if (!EmptyRgn(oldVisRgn)) { HideAnts((*theImage)->ants); theErr = DrawImage(theImage, bfOnscreen, nil); ShowAnts((*theImage)->ants); } CalcVis((WindowPeek)(*theImage)->window); if (IsAboutBox(theImage)) { Rect theRect = (*theImage)->wrect; FontInfo theFontInfo; Str63 theText; TextFont(geneva); TextSize(9); TextMode(srcOr); ClipRect(&theRect); GetFontInfo(&theFontInfo); #if defined(powerc) || defined(__powerc) BlockMove(gString[strVersionPPC], theText, *gString[strVersionPPC] + 1); #else BlockMove(gString[strVersion68k], theText, *gString[strVersion68k] + 1); #endif StuffNumber(theText, 1, (kVersion >> 8) & 0xf); StuffNumber(theText, 2, (kVersion >> 4) & 0xf); MoveTo((*theImage)->wrect.right - StringWidth(theText) - 3, (*theImage)->wrect.top + theFontInfo.ascent + theFontInfo.leading + 3); DrawString(theText); } if (oldVisRgn && EqualRgn(oldVisRgn, (*theImage)->window->visRgn) && !Aborted(theImage)) { SetEmptyRgn((*theImage)->update); DisposeRgn(oldVisRgn); } if (theErr) HandleUpdateError(theImage, theErr); SetStatistics(); PopPort(); StopSpinning(&qd.arrow); return theErr; } static void HandleUpdateError(ImageHandle theImage, OSErr theErr) { if ((theErr == codecBadDataErr) || (gIntError == errCorruptImage)) { if (Corrupt(theImage)) return; (*theImage)->flags |= ifCorrupt; } HandleAEError(theErr, errNoDrawMemory, theImage ? FileName(theImage) : nil); if (theErr == memFullErr) DoCloseWindow((*theImage)->window, gThePrefs.restoreColors); } extern void HandleImageActivate(ImageHandle theImage, Boolean nowActive) { if (theImage) { if (nowActive) ActivateAnts((*theImage)->ants); else DeactivateAnts((*theImage)->ants); } } extern void HandleImageClick(ImageHandle theImage, EventRecord *theEvent) { Boolean inFront = (!gInBackground && (*theImage)->window == FWFrontWindow()); Rect theRect = { 0, 0, 0, 0 }, selRect; Point where = theEvent->where; GetAntsSelection((*theImage)->ants, &selRect); PushPort(); MySetPort((CGrafPtr)(*theImage)->window); // hidden feature: cmd-click forces redraw of window if (theEvent->modifiers & cmdKey) { KillGWorld(theImage); theRect = (*theImage)->wrect; InvalRect(&theRect); inFront = true; goto done; } // check to see if we're even inside the drawing area of the window GlobalToLocal(&where); if (!gSlideShow && !IsAboutBox(theImage) && PtInRect(where, &(*theImage)->wrect)) { // if we're in the size box area, resize the window if (inFront && (((*theImage)->wrect.right - where.h) < 16) && (((*theImage)->wrect.bottom - where.v) < 16)) { Boolean modified = (theEvent->modifiers & (optionKey + cmdKey + shiftKey)) != 0; if (TrackGrowWindow(where, theImage, !modified, &theRect)) { SendSetDrawBounds((*theImage)->window, &theRect); goto done; } } else if (!Full(theImage) || (*theImage)->dmon != gMainMonitor || !gMenuVisible) { // if we're selected, either drag or cancel the selection if (AntsHaveSelection((*theImage)->ants)) { if (PtInRect(where, &selRect) && !EqualRect(&selRect, &(*theImage)->wrect)) { if ((inFront && TrackDragRect(where, theImage) && gDragMgrPresent) || (!inFront && gDragMgrPresent && WaitMouseMoved(theEvent->where))) { DoDragSelection(theImage, theEvent); inFront = true; } GetAntsSelection((*theImage)->ants, &theRect); SendSetSelection(theImage, &theRect); goto done; } } // if we fall through here, we need to track a new selection if (inFront) { SendSetSelection(theImage, &theRect); TrackAntsSelection((*theImage)->ants, where); GetAntsSelection((*theImage)->ants, &theRect); SendSetSelection(theImage, &theRect); if (AntsHaveSelection((*theImage)->ants)) goto done; } // special case: if full screen image overlapped by menubar, treat as window in background } else if (AntsHaveSelection((*theImage)->ants) && PtInRect(where, &selRect) && gDragMgrPresent && WaitMouseMoved(theEvent->where)) { DoDragSelection(theImage, theEvent); inFront = true; } } // if we fall all the way through here, we need to flip the menu bar AdjustMenus(); if (Full(theImage) && (*theImage)->dmon == gMainMonitor && gSlideShow != kPaused) { if (gMenuVisible) { RehideMenuBar(); ActivateAnts((*theImage)->ants); } else { DeactivateAnts((*theImage)->ants); UnhideMenuBar(); } } done: if (!inFront) ChangeActive((*theImage)->window); AdjustMenus(); PopPort(); } static void DoDragSelection(ImageHandle theImage, EventRecord *theEvent) { static DragSendDataProc gSendItemData = nil; RgnHandle theRgn = NewRgn(), tempRgn = NewRgn(); DragReference theDrag; Rect startRect; OSErr theErr; GetAntsSelection((*theImage)->ants, &startRect); if (!gSendItemData) gSendItemData = NewDragSendDataProc((ProcPtr)SendItemData); if (theRgn && tempRgn) { theErr = NewDrag(&theDrag); if (theErr == noErr) { AddDragItemFlavor(theDrag, (ItemReference)theImage, 'PICT', nil, 0, 0); GlobalRect(&startRect, (*theImage)->window); RectRgn(theRgn, &startRect); RectRgn(tempRgn, &startRect); InsetRgn(tempRgn, 1, 1); DiffRgn(theRgn, tempRgn, theRgn); SetDragItemBounds(theDrag, (ItemReference)theImage, &(*theRgn)->rgnBBox); SetDragSendProc(theDrag, gSendItemData, nil); SetCursor(&qd.arrow); theErr = TrackDrag(theDrag, theEvent, theRgn); DisposeDrag(theDrag); } } if (theRgn) DisposeRgn(theRgn); if (tempRgn) DisposeRgn(tempRgn); } static pascal OSErr SendItemData(FlavorType theType, void *dragSendRefCon, ItemReference theItem, DragReference theDrag) { #if applec #pragma unused(dragSendRefCon) #endif Boolean dontDispose = false; PicHandle thePicture; OSErr theErr; switch (theType) { case 'PICT': theErr = GetSelectedPICT((ImageHandle)theItem, &thePicture); if (theErr == noErr) { if (!thePicture) { thePicture = (PicHandle)(*(ImageHandle)theItem)->data; dontDispose = true; } HLock((Handle)thePicture); theErr = SetDragItemFlavorData(theDrag, theItem, 'PICT', *thePicture, GetHandleSize((Handle)thePicture), 0); if (!dontDispose) DisposeHandle((Handle)thePicture); } break; default: theErr = badDragFlavorErr; break; } return theErr; } /* * NewImage() * * Purpose: Adds a new image to the linked list * Inputs: none * Returns: a pointer to the new image * */ ImageHandle NewImage(void) { ImageHandle theImage; if (gImageRoot) { theImage = LastImage(); theImage = (*theImage)->next = (ImageHandle)NewHandleClear(sizeof(ImageItem)); } else theImage = gImageRoot = (ImageHandle)NewHandleClear(sizeof(ImageItem)); (*theImage)->id = kImageID; (*theImage)->update = NewRgn(); (*theImage)->ants = NewAnts(); return theImage; } /* * DisposeImage(theImage) * * Purpose: Removes the given image from the linked list * Inputs: theImage = the image record to be removed * Returns: nothing * */ void DisposeImage(ImageHandle theImage) { Boolean foundData = false, foundGWorld = false; ImageHandle tempImage; PushPort(); MySetPort(nil); (*theImage)->id = 0; for (tempImage = gImageRoot; tempImage; tempImage = (*tempImage)->next) if (tempImage != theImage) { if ((*tempImage)->data == (*theImage)->data) foundData = true; if ((*tempImage)->gworld == (*theImage)->gworld) foundGWorld = true; } if (!foundData && (*theImage)->data) DisposeHandle((*theImage)->data); if (!foundGWorld) KillGWorld(theImage); if ((*theImage)->ipalette) DisposePalette((*theImage)->ipalette); if ((*theImage)->qpalette) DisposePalette((*theImage)->qpalette); if ((*theImage)->palette) DisposePalette((*theImage)->palette); if ((*theImage)->comments) DisposeHandle((*theImage)->comments); if ((*theImage)->window) { FWCloseWindow((*theImage)->window); DeallocateWindow((*theImage)->window); } if ((*theImage)->update) DisposeRgn((*theImage)->update); if ((*theImage)->format && (*theImage)->format->close) (*theImage)->format->close(theImage); if ((*theImage)->privateData) DisposeHandle((*theImage)->privateData); if (theImage != gImageRoot) (*PreviousImage(theImage))->next = (*theImage)->next; else gImageRoot = (*gImageRoot)->next; if ((*theImage)->ants) DisposeAnts((*theImage)->ants); DisposeHandle((Handle)theImage); PopPort(); } /* * CopyImage(theImage) * * Purpose: Makes a copy of the given image * Inputs: theImage = the image record to be copied * Returns: a pointer to a new copy of the image * */ ImageHandle CopyImage(ImageHandle srcImage) { ImageHandle dstImage, theImage; PaletteHandle newPalette; AntsReference oldAnts; RgnHandle oldUpdate; Handle tmpHandle; if (dstImage = NewImage()) { oldUpdate = (*dstImage)->update; oldAnts = (*dstImage)->ants; BlockMove(*srcImage, *dstImage, sizeof(ImageItem)); (*dstImage)->update = oldUpdate; (*dstImage)->ants = oldAnts; (*dstImage)->next = nil; (*dstImage)->window = nil; if ((*srcImage)->palette) { newPalette = NewPalette((*(*srcImage)->palette)->pmEntries, nil, pmTolerant, 0); if (newPalette) { CopyPalette((*srcImage)->palette, newPalette, 0, 0, (*(*srcImage)->palette)->pmEntries); (*dstImage)->palette = newPalette; } } if ((*srcImage)->qpalette) { newPalette = NewPalette((*(*srcImage)->qpalette)->pmEntries, nil, pmTolerant, 0); if (newPalette) { CopyPalette((*srcImage)->qpalette, newPalette, 0, 0, (*(*srcImage)->qpalette)->pmEntries); (*dstImage)->qpalette = newPalette; } } if ((*srcImage)->ipalette) { newPalette = NewPalette((*(*srcImage)->ipalette)->pmEntries, nil, pmTolerant, 0); if (newPalette) { CopyPalette((*srcImage)->ipalette, newPalette, 0, 0, (*(*srcImage)->ipalette)->pmEntries); (*dstImage)->ipalette = newPalette; } } tmpHandle = (*dstImage)->comments; if (tmpHandle) { HandToHand(&tmpHandle); (*dstImage)->comments = tmpHandle; } tmpHandle = (*dstImage)->privateData; if (tmpHandle) { HandToHand(&tmpHandle); (*dstImage)->privateData = tmpHandle; } if ((*srcImage)->format->clone) (*srcImage)->format->clone(srcImage, dstImage); (*dstImage)->flags &= ~(ifSelected + ifSelVisible + ifAborted + ifScreenSize + ifFilename); for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if ((theImage != dstImage) && ((*theImage)->num >= (*dstImage)->num)) (*dstImage)->num = (*theImage)->num + 1; } return dstImage; } /* * LastImage() * * Purpose: Returns a pointer to the last image in the linked list * Inputs: none * Returns: a pointer to the last image, or nil if no images exist * */ ImageHandle LastImage(void) { ImageHandle theImage; if (!gImageRoot) return nil; for (theImage = gImageRoot; (*theImage)->next; theImage = (*theImage)->next); return theImage; } /* * PreviousImage(theImage) * * Purpose: Returns a pointer to the image preceding theImage in the linked list * Inputs: none * Returns: a pointer to the preceding image, or nil if theImage is gImageRoot * */ ImageHandle PreviousImage(ImageHandle theImage) { ImageHandle curImage; if (theImage == gImageRoot) return nil; for (curImage = gImageRoot; curImage && ((*curImage)->next != theImage); curImage = (*curImage)->next); return curImage; } /* * AnotherFull(theImage) * * Purpose: Determines if there is another full-screen image on the same monitor as * theImage * Inputs: theImage = a handle to the image * Returns: true if there is another full-screen image; false otherwise * */ Boolean AnotherFull(ImageHandle theImage) { MonitorHandle imageMon = theImage ? (*theImage)->dmon : gMainMonitor; ImageHandle fullImage; if (imageMon == gMainMonitor && GetSlideBackWindow()) return true; for (fullImage = gImageRoot; fullImage; fullImage = (*fullImage)->next) if ((fullImage != theImage) && Full(fullImage) && (*fullImage)->dmon == imageMon) break; return (fullImage != nil); } /* * FindImage(theWindow) * * Purpose: Scans the list of images for one who owns the given window * Inputs: theWindow = a pointer to the window record * Returns: a pointer to the associated image, or nil if none found * */ ImageHandle FindImage(WindowPtr theWindow) { ImageHandle theImage; if (theWindow) for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if ((*theImage)->window == theWindow) return theImage; return nil; } /* * UpdateImages(theMonitor) * * Purpose: Updates any images whose deepest monitor happens to be theMonitor * Inputs: theMonitor = the monitor whose state has changed * Returns: nothing * */ void UpdateImages(MonitorHandle theMonitor) { #if applec #pragma unused(theMonitor) #endif short depth, palette; ImageHandle theImage; Boolean grey; for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) { GetMinMaxMonitor(theImage); depth = (*(*theImage)->dmon)->depth; grey = !(*(*theImage)->dmon)->color; if (grey || (depth < 4)) palette = plGrey; else if (depth > 8) palette = plSys; else palette = (*theImage)->npalette; switch (palette) { case plSys: DoSetPalette((*theImage)->window, kAEPSystem); break; case plGrey: DoSetPalette((*theImage)->window, kAEPGrayscale); break; case plImage: if ((*(*theImage)->ipalette)->pmEntries <= (1L << depth)) DoSetPalette((*theImage)->window, kAEPImage); else DoSetPalette((*theImage)->window, kAEPSystem); break; case plQuant: if ((*theImage)->qpalette && ((1L << depth) != ((*(*theImage)->qpalette)->pmEntries))) { DisposePalette((*theImage)->qpalette); (*theImage)->qpalette = nil; DoSetPalette((*theImage)->window, kAEPSystem); } else DoSetPalette((*theImage)->window, kAEPQuantized); break; } if (!gThePrefs.ditherQuant && ((*theImage)->npalette == plQuant || ((*theImage)->npalette == plImage && (*theImage)->depth >= 16))) (*theImage)->flags &= ~ifDithered; else (*theImage)->flags |= ifDithered; } } /* * DrawImage(theImage) * * Purpose: Draws the given image in its window * Inputs: theImage = the image record to be drawn * bitsFlags = the initial set of bitsFlags * Returns: nothing * */ OSErr DrawImage(ImageHandle theImage, short bitsFlags, NestedProgressPtr progProc) { Rect theRect = (*theImage)->wrect; OSErr theErr = noErr; RgnHandle tmpRgn; PushPort(); MySetPort((CGrafPtr)(*theImage)->window); /* If we're drawing onscreen, erase the region to be updated, draw a border around * full screen images, reset the clipping rectangle, and limit the visRgn to the * clipped area (since we assume we're doing this from within an update event */ if (bitsFlags & bfOnscreen) { CopyRgn((*theImage)->window->visRgn, (*theImage)->update); if (Full(theImage) && (tmpRgn = NewRgn())) { ClipRect(&(*theImage)->window->portRect); RectRgn(tmpRgn, &theRect); DiffRgn((*theImage)->window->clipRgn, tmpRgn, (*theImage)->window->clipRgn); if (NeedsWhiteBG(theImage) && !Full(theImage)) EraseRgn((*theImage)->window->visRgn); else PaintRgn((*theImage)->window->visRgn); DrawFullBorder(theImage); DisposeRgn(tmpRgn); DiffRgn((*theImage)->update, (*theImage)->window->clipRgn, (*theImage)->update); DiffRgn((*theImage)->window->visRgn, (*theImage)->window->clipRgn, (*theImage)->window->visRgn); } } ClipRect(&theRect); /* If we have anything to draw, then set up the global bitsFlags, point to our * special drawing procedures, and do the appropriate method of drawing */ if (bitsFlags != bfOnscreen || !EmptyRgn((*theImage)->window->visRgn)) { if ((*theImage)->gworld) LockPixels(GetGWorldPixMap((*theImage)->gworld)); if ((*theImage)->gworld && !(bitsFlags & bfForceFull)) theErr = DrawImageGWorld(theImage, bitsFlags, progProc); else theErr = DrawImageFull(theImage, bitsFlags, progProc); } if ((theErr == noErr) && Full(theImage) && (bitsFlags & bfOnscreen) && ShowFilename(theImage)) DrawFileName(theImage); if (bitsFlags & bfOnscreen) { if (theErr == codecAbortErr && !(bitsFlags & bfQuantize)) { if (NeedToRedraw(theImage)) (*theImage)->flags &= ~(ifNeedToRedraw + ifAborted); else { Pattern whitePat = { 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x00 }; Pattern blackPat = { 0x7d, 0xbb, 0xd7, 0xef, 0xd7, 0xbb, 0x7d, 0xff }; RGBForeColor(&gBlack); RGBBackColor(&gWhite); SetClip((*theImage)->update); FillRgn((*theImage)->update, NeedsWhiteBG(theImage) ? &whitePat : &blackPat); (*theImage)->flags |= ifAborted; } } else (*theImage)->flags &= ~ifAborted; } if ((*theImage)->gworld) UnlockPixels(GetGWorldPixMap((*theImage)->gworld)); PopPort(); return theErr; } /* * DrawImageGWorld(theImage, bitsFlags) * * Purpose: Handles drawing from the offscreen GWorld * Inputs: theImage = the image record to be drawn * bitsFlags = set of flags to be passed on to the custom copybits * Returns: nothing * */ OSErr DrawImageGWorld(ImageHandle theImage, short bitsFlags, NestedProgressPtr progProc) { PixMapHandle src = GetGWorldPixMap((*theImage)->gworld); Boolean deepGWorld = ((*(*theImage)->dmon)->depth < PixMapDepth(src)) && !gThePrefs.origSize; Rect srcRect = GWOrigSize(theImage) ? (*theImage)->crect : (*theImage)->gworld->portRect; GWorldPtr oldGWorld = (*theImage)->gworld; Rect theRect = (*theImage)->wrect; JVDrawParamsHandle theParams; OSErr theErr = noErr; KeepSpinning(); if (theParams = NewDrawParams(&(*theImage)->gworld->portRect, (*theImage)->quality, (bitsFlags & bfQuantize) != 0, progProc, (*theImage)->privateData)) { SetUpDrawPort(theParams, kOnscreenPort, (CGrafPtr)(*theImage)->window, &srcRect, &theRect, Dithered(theImage)); (*theParams)->newupdates = (*theImage)->update; // if the GWorld is too deep, we need to delete it and make a new one if (deepGWorld) { (*theImage)->gworld = nil; (*theImage)->flags &= ~ifGWOrigSize; if (!MakeImageGWorld(theImage, false)) { DisposeGWorld(oldGWorld); DisposeHandle((Handle)theParams); if (gThePrefs.useBitmaps == ubAlways && !gSlideShow) return gIntError = errNoOffscreenMemory, memFullErr; else return DrawImageFull(theImage, bitsFlags, progProc); } SetUpDrawPort(theParams, kOffscreenPort1, (*theImage)->gworld, &srcRect, &(*theImage)->gworld->portRect, true); LockPixels(GetGWorldPixMap((*theImage)->gworld)); } // save the port, lock the handles, and initialize the drawing theErr = PreflightDrawing(theParams); // If everything's okay, CopyBits to the dummy port and clean up if (theErr == noErr) { SpinIndef(); CopyGWorldToGWorld(oldGWorld, (*theParams)->dummy, &srcRect, &srcRect, srcCopy, nil); theErr = PostflightDrawing(theParams); } KeepSpinning(); if (deepGWorld) { UnlockPixels(GetGWorldPixMap((*theImage)->gworld)); DisposeGWorld(oldGWorld); } if (progProc) *progProc = (*theParams)->progress; DisposeHandle((Handle)theParams); } else theErr = MemError(); if (theErr == codecAbortErr && (bitsFlags & bfOffscreen)) KillGWorld(theImage); return theErr; } /* * DrawImageFull(theImage, bitsFlags) * * Purpose: Handles drawing from scratch * Inputs: theImage = the image record to be drawn * bitsFlags = set of flags to be passed on to the custom copybits * progProc = pointer to the progress procedure, or nil to use the default * Returns: nothing * */ OSErr DrawImageFull(ImageHandle theImage, short bitsFlags, NestedProgressPtr progProc) { NestedProgress localProg = { { nil, 0L }, 0, 0L, 0x10000L, false }; Rect crect = (*theImage)->crect, theRect = (*theImage)->wrect; JVDrawParamsHandle theParams; OSErr theErr; long dtime; KeepSpinning(); // erase the area we're drawing into before doing anything else if (bitsFlags & bfOnscreen) { if (NeedsWhiteBG(theImage)) EraseRgn((*theImage)->window->visRgn); else PaintRgn((*theImage)->window->visRgn); } // set up the progress procedure, according to flags & current situation & such if (progProc) localProg = *progProc; else { if (bitsFlags & bfOnscreen) { if (NoOnscreenProg(theImage)) localProg.prog.progressProc = gDummyProg.prog.progressProc; else localProg.prog.progressProc = gDrawProgress; } else if (bitsFlags & bfUseSlideProgress) localProg.prog.progressProc = gSlideProgress; else localProg.prog.progressProc = gGenericProgress; } // allocate and initialize the drawing parameters if (theParams = NewDrawParams(&(*theImage)->grect, (*theImage)->quality, (bitsFlags & bfQuantize) != 0, &localProg, (*theImage)->privateData)) { if (localProg.prog.progressProc == gDrawProgress) (*theParams)->drawProgressRect = (*theImage)->wrect; // set up the onscreen port if (bitsFlags & bfOnscreen) { SetUpDrawPort(theParams, kOnscreenPort, (CGrafPtr)(*theImage)->window, &crect, &theRect, Dithered(theImage)); (*theParams)->newupdates = (*theImage)->update; } // try to make a GWorld for this image; if successful, set the bitsFlags // and ClipRgn appropriately; otherwise, if we've required bitmaps, close the // image and return an error if (!(*theImage)->gworld) { if (MakeImageGWorld(theImage, bitsFlags & bfQuantize)) { LockPixels(GetGWorldPixMap((*theImage)->gworld)); bitsFlags |= bfOffscreen; } else if (gThePrefs.useBitmaps == ubAlways && !gSlideShow && ((*theImage)->compression || !gThePrefs.noUncomp)) return gIntError = errNoOffscreenMemory, memFullErr; } // set up the offscreen port if ((bitsFlags & bfOffscreen) && (*theImage)->gworld) SetUpDrawPort(theParams, kOffscreenPort1, (*theImage)->gworld, GWOrigSize(theImage) ? &(*theImage)->gworld->portRect : &crect, &(*theImage)->gworld->portRect, !GWOrigSize(theImage)); // spin the cursor, start the timer, and preflight our drawing KeepSpinning(); StartTimer(); theErr = PreflightDrawing(theParams); KeepSpinning(); PushPort(); if (theErr == noErr) { // indicate globally that we are drawing, and actually call the function gDrawing = theImage; MySetPort((*theParams)->dummy); CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressOpen, 0L, (*theParams)->progress.prog.progressRefCon); theErr = (*theImage)->format->draw((*theImage)->data, theParams); CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressClose, 0L, (*theParams)->progress.prog.progressRefCon); // reset everything now and stop the timer gDrawing = nil; KeepSpinning(); dtime = StopTimer(); // if we were drawing a full-size image, save the time from the timer if (EqualSizeRect(&theRect, &(*(*theImage)->window->visRgn)->rgnBBox) && theErr == noErr && (bitsFlags & (bfOnscreen + bfOffscreen))) (*theImage)->dtime = dtime; // postflight the drawing, saving the error if (theErr == noErr) theErr = PostflightDrawing(theParams); else PostflightDrawing(theParams); } PopPort(); if (progProc) *progProc = (*theParams)->progress; DisposeHandle((Handle)theParams); } else theErr = memFullErr; if (theErr == memFullErr) gIntError = errNoDrawMemory; else if (theErr == codecAbortErr && (bitsFlags & bfOffscreen)) KillGWorld(theImage); return theErr; } /* * DrawFullBorder(theImage) * * Purpose: Draws the border for a full-screen window * Inputs: theImage = the image record to be drawn * Returns: nothing * */ void DrawFullBorder(ImageHandle theImage) { Rect outerRect = (*theImage)->wrect; InsetRect(&outerRect, -1, -1); RGBForeColor(&gFGrey); RGBBackColor(&gWhite); FrameRect(&outerRect); MoveTo(outerRect.left + 1, outerRect.bottom); LineTo(outerRect.right, outerRect.bottom); LineTo(outerRect.right, outerRect.top + 1); RGBForeColor(&gBlack); } /* * DrawFileName(theImage) * * Purpose: Draws a filename on a full-screen window for the slide show * Inputs: theImage = the image record to be drawn * Returns: nothing * */ void DrawFileName(ImageHandle theImage) { short height, width, i, j; FontInfo theInfo; Str255 theText; Point start; if (!theImage || !(*theImage)->window) return; PushPort(); MySetPort((CGrafPtr)(*theImage)->window); ClipRect(&(*theImage)->window->portRect); CalcVis((WindowPeek)(*theImage)->window); // Do this to get the real visRgn of the window TextFont(systemFont); TextFace(normal); TextSize(12); TextMode(srcOr); GetFontInfo(&theInfo); BlockMove((*theImage)->file.name, theText, *(*theImage)->file.name + 1); height = theInfo.ascent + theInfo.descent + theInfo.leading; width = StringWidth(theText); /* If there's enough room, simply draw the file name below the image's rect */ if (((*theImage)->wrect.bottom + height) < (*(*theImage)->dmon)->rect.bottom) { start.h = (*theImage)->wrect.right - width - theInfo.leading; start.v = (*theImage)->wrect.bottom + height - theInfo.leading; RGBForeColor(&gWhite); MoveTo(start.h, start.v); DrawString(theText); /* Or we could draw it to the right of the image's rect */ } else if (((*theImage)->wrect.right + width + 4) < (*(*theImage)->dmon)->rect.right) { start.h = (*theImage)->wrect.right + 4; start.v = (*theImage)->wrect.bottom - theInfo.descent - theInfo.leading; RGBForeColor(&gWhite); MoveTo(start.h, start.v); DrawString(theText); /* If there's not enough room, we draw the filename on top of the lower-right corner */ } else { start.h = (*theImage)->wrect.right - width - theInfo.leading; start.v = (*theImage)->wrect.bottom - theInfo.descent - theInfo.leading; RGBForeColor(&gBlack); for (i = -1; i <= 1; i++) for (j = -1; j <= 1; j++) { MoveTo(start.h + i, start.v + j); DrawString(theText); } RGBForeColor(&gWhite); MoveTo(start.h, start.v); DrawString(theText); } RGBForeColor(&gBlack); PopPort(); } /* * MakeImageGWorld(theImage) * * Purpose: Attempts to create a new offscreen bitmap for the given image * Inputs: theImage = the image record * quantizing = flag: true if we're quantizing * Returns: true if it worked; false otherwise * */ Boolean MakeImageGWorld(ImageHandle theImage, Boolean quantizing) { short imageDepth = ((*theImage)->depth < 8) ? 8 : (*theImage)->depth; short theDepth = (*(*theImage)->dmon)->depth; Rect theRect = (*theImage)->wrect; CTabHandle theColors = nil; if (gThePrefs.noUncomp && !(*theImage)->compression) return false; if (gThePrefs.useBitmaps == ubNever && (!gSlideShow || !(*gSlideOptions)->offscreen)) return false; if (gThePrefs.origSize && (!Banded(theImage) || !Cropped(theImage))) theRect = (*theImage)->grect; if (theDepth > imageDepth || gThePrefs.origSize || quantizing) theDepth = imageDepth; if (theDepth == 24) theDepth = 32; else if (theDepth <= 8) theColors = GetGWorldColors(theImage, theDepth); OffsetRect(&theRect, (*theImage)->grect.left - theRect.left, (*theImage)->grect.top - theRect.top); (*theImage)->gworld = nil; if (IsMemAvailable(EstGWorldSize(&theRect, theDepth))) (*theImage)->gworld = MyNewGWorld(&theRect, theDepth, theColors, nil, NeedsWhiteBG(theImage), false); if (!(*theImage)->gworld && gSlideShow && (*gSlideOptions)->offscreen && !HasVirtualMemory()) { (*theImage)->gworld = MyNewGWorld(&theRect, theDepth, theColors, nil, NeedsWhiteBG(theImage), true); if ((*theImage)->gworld) (*theImage)->flags |= ifGWTempMem; } if ((*theImage)->gworld) { (*theImage)->flags &= ~ifGWOrigSize; if (EqualSizeRect(&theRect, &(*theImage)->grect) && theDepth >= (*theImage)->depth && (gThePrefs.origSize || theDepth >= 16)) (*theImage)->flags |= ifGWOrigSize; if (theColors) DisposeHandle((Handle)theColors); return true; } if (theColors) DisposeHandle((Handle)theColors); return false; } /* * KillGWorld(theImage) * * Purpose: Kills the given image's GWorld and checks for others who might share it * Inputs: theImage = the image record whose GWorld we are about to kill * Returns: nothing * */ void KillGWorld(ImageHandle theImage) { GWorldPtr theGWorld, curPort = (GWorldPtr)qd.thePort; Boolean foundOthers = false; ImageHandle image; if (theImage && (theGWorld = (*theImage)->gworld)) { if (curPort == theGWorld) MySetPort(nil); for (image = gImageRoot; image; image = (*image)->next) if (image != theImage && (*image)->gworld == theGWorld) foundOthers = true; if (!foundOthers) DisposeGWorld(theGWorld); (*theImage)->gworld = nil; } } /* * GetGWorldColors(theImage, gwDepth) * * Purpose: Creates an appropriate color table for the given image's GWorld at the * given depth * Inputs: theImage = the image record * gwDepth = the depth of the GWorld we'd like to create * Returns: a CTabHandle containing the color table * */ CTabHandle GetGWorldColors(ImageHandle theImage, short gwDepth) { short imDepth = (*theImage)->depth; PaletteHandle thePalette = nil; CTabHandle theColors = nil; if (!gThePrefs.origSize) { // can only copy from screen if not original size if ((theImage == FrontImage()) && !gInBackground && (*theImage)->window && WindowVisible((*theImage)->window) && (gwDepth == (*(*theImage)->dmon)->depth) && (gwDepth <= 8)) { theColors = (*(*(*(*theImage)->dmon)->device)->gdPMap)->pmTable; if (HandToHand((Handle *)&theColors) != noErr) theColors = nil; return theColors; } } if (gwDepth >= imDepth) { if (imDepth <= 8) { if (gwDepth <= 8) thePalette = (*theImage)->ipalette ? (*theImage)->ipalette : (*theImage)->palette; else thePalette = nil; } else thePalette = nil; } else { if (imDepth <= 8) thePalette = (*theImage)->palette; else { if (gwDepth <= 8) thePalette = (*theImage)->palette; else thePalette = nil; } } if (thePalette && ((1L << gwDepth) == (*thePalette)->pmEntries)) { if (theColors = (CTabHandle)NewHandle(4)) { Palette2CTab(thePalette, theColors); (*theColors)->ctSeed = GetCTSeed(); } } return theColors; } /* * DoImageHelp(theWindow, globalPt) * * Purpose: Pops up help for an image window; needed because they can be called anything * Inputs: theWindow = the window whose help we're getting * globalPt = point, in global coordinates, where the mouse is * Returns: nothing * */ void DoImageHelp(WindowPtr theWindow, Point globalPt) { ImageHandle theImage = FindImage(theWindow); HMMessageRecord theRecord; Point tip = { 0, 0 }; Rect aRect; if (HMIsBalloon() || gInBackground) return; PushPort(); SetPort(theWindow); if (HMExtractHelpMsg(kHMRectListResType, rImageWindow, 1, kHMEnabledItem, &theRecord) == noErr) { tip = globalPt; aRect = theWindow->portRect; GlobalRect(&aRect, theWindow); HMShowBalloon(&theRecord, tip, &aRect, nil, 0, 0, kHMRegularWindow); } PopPort(); } \ No newline at end of file diff --git a/Source/C/InitRegion.c b/Source/C/InitRegion.c new file mode 100644 index 0000000..1a5057f --- /dev/null +++ b/Source/C/InitRegion.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // short *InitRegion(RgnPtr rgn, RgnBufferPtr rgnBuffer, Rect *boxRect) short *rgnData = (short *)(&rgn->rgnBBox + 1); long *bufData = rgnBuffer->buffer; long x; if (rgn->rgnSize == 10) { rgnBuffer->yCount = Height(&rgn->rgnBBox); *bufData++ = 0; *bufData++ = Width(&rgn->rgnBBox); } else if (!(rgnBuffer->yCount = *rgnData++ - boxRect->top)) { while ((x = *rgnData++) != 0x7fff) *bufData++ = x - boxRect->left; rgnBuffer->yCount = *rgnData++ - boxRect->top; } *bufData++ = 0x7fff; return rgnData; /* r3 = rgn r4 = rgnBuffer r5 = boxRect 00000000: BFA1FFF4 stmw r29,-12(SP) short *rgnData = (short *)(&rgn->rgnBBox + 1); long *bufData = rgnBuffer->buffer; long x; 00000004: A8C30000 lha r6,0(rgn) ;r6 = rgn->rgnSize 00000008: 3BC3000A addi rgnData,rgn,10 ;r30 = rgnData = (short *)(&rgn->rgnBBox + 1) 0000000C: 2C06000A cmpwi r6,10 ;is rgn->rgnSize == 10? 00000010: 3BA40008 addi bufData,rgnBuffer,8 ;r29 = bufData = rgnBuffer->buffer 00000014: 40820040 bne $00000054 ;if (rgn->rgnSize == 10) { if (rgn->rgnSize == 10) { rgnBuffer->yCount = Height(&rgn->rgnBBox); *bufData++ = 0; *bufData++ = Width(&rgn->rgnBBox); } else 00000018: A8E30002 lha r7,2(rgn) ; r7 = rgn->rgnBBox.top 0000001C: A9030006 lha r8,6(rgn) ; r8 = rgn->rgnBBox.bottom 00000020: 7FAAEB78 mr r10,bufData ; r10 = r29 = bufData 00000024: 7CE74050 sub r7,r8,r7 ; r7 = Height(&rgn->rgnBBox) 00000028: 90E40000 stw r7,0(rgnBuffer) ; rgnBuffer->yCount = r7 0000002C: 39200000 li r9,0 ; r9 = 0 00000030: 912A0000 stw r9,0(r10) ; *r10 = r9 = 0 00000034: A9630004 lha r11,4(rgn) ; r11 = rgn->rgnBBox.left 00000038: A9830008 lha r12,8(rgn) ; r12 = rgn->rgnBBox.right 0000003C: 3BBD0004 addi bufData,bufData,4 ; bufData++ 00000040: 7FA6EB78 mr r6,bufData ; r6 = r29 = bufData 00000044: 7D6B6050 sub r11,r12,r11 ; r11 = Width(&rgn->rgnBBox) 00000048: 3BBD0004 addi bufData,bufData,4 ; bufData++ 0000004C: 91660000 stw r11,0(r6) ; *r6 = r11 00000050: 42800068 bc ALWAYS,cr0_LT,$000000B8 ;} else if (!(rgnBuffer->yCount = *rgnData++ - boxRect->top)) { while ((x = *rgnData++) != 0x7fff) *bufData++ = x - boxRect->left; rgnBuffer->yCount = *rgnData++ - boxRect->top; } 00000054: 7FC8F378 mr r8,rgnData ; r8 = r30 = rgnData 00000058: A8E50000 lha r7,0(boxRect) ; r7 = boxRect->top 0000005C: A9080000 lha r8,0(r8) ; r8 = *r8 00000060: 3BDE0002 addi rgnData,rgnData,2 ; rgnData++ 00000064: 7CE74050 sub r7,r8,r7 ; r7 = r8 - boxRect->top 00000068: 2C070000 cmpwi r7,0 ; is r7 0? 0000006C: 90E40000 stw r7,0(rgnBuffer) ; rgnBuffer->yCount = r7 00000070: 40820048 bne $000000B8 ; if (!rgnBuffer->yCount) { 00000074: 42800018 bc ALWAYS,cr0_LT,$0000008C ; while () { 00000078: A9250002 lha r9,2(boxRect) ; r9 = boxRect->left 0000007C: 7FAAEB78 mr r10,bufData ; r10 = bufData 00000080: 7D29F850 sub r9,x,r9 ; r9 = r31 - r9 00000084: 3BBD0004 addi bufData,bufData,4 ; bufData++ 00000088: 912A0000 stw r9,0(r10) ; *r10 = r9 0000008C: 7FCBF378 mr r11,rgnData ; r11 = rgnData 00000090: ABEB0000 lha x,0(r11) ; r31 = *r11 00000094: 3BDE0002 addi rgnData,rgnData,2 ; rgnData++ 00000098: 2C1F7FFF cmpwi x,32767 ; is r31 == 0x7fff? 0000009C: 4082FFDC bne $00000078 ; } 000000A0: 7FC6F378 mr r6,rgnData ; r6 = rgnData 000000A4: A9850000 lha r12,0(boxRect) ; r12 = boxRect->top 000000A8: A8C60000 lha r6,0(r6) ; r6 = *r6 000000AC: 3BDE0002 addi rgnData,rgnData,2 ; rgnData++ 000000B0: 7D8C3050 sub r12,r6,r12 ; r12 = r6 - r12 000000B4: 91840000 stw r12,0(rgnBuffer) ; rgnBuffer->yCount = r12 ; } *bufData++ = 0x7fff; return rgnData; 000000B8: 7FA8EB78 mr r8,bufData ;r8 = bufData 000000BC: 38E07FFF li r7,32767 ;r7 = 0x7fff 000000C0: 3BBD0004 addi bufData,bufData,4 ;bufData++ 000000C4: 90E80000 stw r7,0(r8) ;*r8 = r7 000000C8: 7FC3F378 mr r3,rgnData ;r3 = rgnData 000000CC: BBA1FFF4 lmw r29,-12(SP) 000000D0: 4E800020 blr */ \ No newline at end of file diff --git a/Source/C/JPEG.c b/Source/C/JPEG.c new file mode 100644 index 0000000..090135c --- /dev/null +++ b/Source/C/JPEG.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "JPEG.h" //===================================================================================== // Global variables local to this module //===================================================================================== static Handle gJPEGDestHandle; static CTabHandle gJFIFColors = nil; static StdPixUPP gUnwrapPixProc = nil; static QDBitsUPP gDummyBitsProc; static QDTextUPP gDummyTextProc; static QDLineUPP gDummyLineProc; static QDRectUPP gDummyRectProc; static QDRRectUPP gDummyRRectProc; static QDOvalUPP gDummyOvalProc; static QDArcUPP gDummyArcProc; static QDPolyUPP gDummyPolyProc; static QDRgnUPP gDummyRgnProc; // JPEG quantization tables for identifying IJG-compressed images static ushort gIJGLumiTab[64] = { 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, 40, 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, 57, 51, 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, 109, 81, 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, 100, 120, 92, 101, 103, 99 }; static ushort gIJGChromTab[64] = { 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr DrawJPEGQuickTime(Handle theHandle, JVDrawParamsHandle theParams); static void InitJPEGUPPs(void); static uchar *GetJPEGData(uchar *theAdr, long theLen, uchar theCode); static void GetJPEGInfo(ImageHandle theImage); static Boolean CalcIJGTable(ushort theID, uchar *theData, long *theQuality); static Boolean CalcAppleTable(ushort theID, uchar *theData, long *theQuality); static OSErr CompressJFIFPreview(PixMapHandle thePixMap, Rect *theRect, Handle *theHandle); static OSErr WriteJFIFHeader(short theFile, GWorldPtr thePreview, Rect *theRect); static OSErr MakeJPEGImageDesc(Handle theHandle, ImageDescriptionHandle theDesc); static pascal void UnwrapPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short callOldBits); static pascal void DummyBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask); static pascal void DummyTextProc(short count, const void *textAddr, Point numer, Point denom); static pascal void DummyLineProc(Point newPt); static pascal void DummyRectProc(GrafVerb verb, const Rect *r); static pascal void DummyRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, short ovalHeight); static pascal void DummyOvalProc(GrafVerb verb, const Rect *r); static pascal void DummyArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle); static pascal void DummyPolyProc(GrafVerb verb, PolyHandle poly); static pascal void DummyRgnProc(GrafVerb verb, RgnHandle rgn); //===================================================================================== // Boolean VerifyJPEGData(uchar *theData, long theSize) //===================================================================================== // Does a quick sanity check on the JPEG data. //===================================================================================== extern Boolean VerifyJPEGData(uchar *theData, long theSize) { return (GetJPEGData(theData, theSize, 0xd9) != nil); } //===================================================================================== // Boolean idJPEG(uchar *theData, long theSize) //===================================================================================== // Examines the given data and attempts to identify it as a JPEG image. //===================================================================================== extern Boolean idJPEG(uchar *theData, long theSize, short refNum, FSSpec *theSpec) { #if applec #pragma unused(refNum, theSpec) #endif return (theSize > 4 && theData[0] == 0xff && theData[1] == 0xd8 && theData[2] == 0xff); } //===================================================================================== // OSErr OpenJPEG(ImageHandle theImage) //===================================================================================== // Initializes the image record for a JPEG image. //===================================================================================== extern OSErr OpenJPEG(ImageHandle theImage) { long theLen = GetHandleSize((*theImage)->data); FSSpec theSpec = (*theImage)->file; Handle theComments = nil; uchar *theData, theCode; OSErr theErr = noErr; short refNum; // if (!gQTVersion) gIntError = errNoQuickTime, theErr = codecBadDataErr; if (refNum = FSpOpenResFile(&theSpec, fsRdPerm)) { CTabHandle theColors; if (theColors = (CTabHandle)Get1Resource('clut', 0)) (*theImage)->ipalette = NewPalette((*theColors)->ctSize + 1, theColors, pmTolerant, 0); CloseResFile(refNum); } if (!VerifyJPEGData((uchar *)*(*theImage)->data, theLen)) gIntError = errCorruptImage, theErr = errBadJPEG; for (theCode = 0xc0; theCode < 0xd0; theCode++) if (theData = GetJPEGData((uchar *)*(*theImage)->data, theLen, theCode)) break; if (theCode == 0xd0) return gIntError = errCorruptImage, codecBadDataErr; GetJPEGInfo(theImage); (*theImage)->compression = kJPEGCompression; MySetRect(&(*theImage)->grect, 0, 0, (theData[3] << 8) + theData[4], (theData[1] << 8) + theData[2]); if (theData[5] == 3) (*theImage)->depth = 32; else if (theData[5] == 1) { (*theImage)->depth = 8; (*theImage)->ipalette = NewPalette(256, nil, pmTolerant, 0); if ((*theImage)->ipalette) CopyPalette(GreyPalette(8), (*theImage)->ipalette, 0, 0, 256); } else gIntError = errCorruptImage, errBadJPEG; (*theImage)->crect = (*theImage)->qrect = (*theImage)->grect; HLock((*theImage)->data); ExtractComments(*(*theImage)->data, GetHandleSize((*theImage)->data), &theComments); HUnlock((*theImage)->data); (*theImage)->comments = theComments; if ((*theImage)->desc.spatialQuality) { Str63 theDesc; BlockMove(gString[strIJGJPEG], theDesc, *gString[strIJGJPEG] + 1); StuffNumber(theDesc, 1, (*theImage)->desc.spatialQuality); BlockMove(theDesc, (*theImage)->compressionDesc, *theDesc + 1); } else BlockMove((*theImage)->desc.name, (*theImage)->compressionDesc, *(*theImage)->desc.name + 1); return theErr; } //===================================================================================== // OSErr DrawJPEG(Handle theHandle, JVDrawParamsHandle theParams) //===================================================================================== // Draws a JPEG image, whose data is in theHandle, to the destination described in the // drawing parameters. //===================================================================================== extern OSErr DrawJPEG(Handle theHandle, JVDrawParamsHandle theParams) { if (!gQTVersion || !gThePrefs.useQuickTime) return DrawJPEGNoQuickTime(theHandle, theParams); else return DrawJPEGQuickTime(theHandle, theParams); } //===================================================================================== // OSErr DrawJPEG(Handle theHandle, JVDrawParamsHandle theParams) //===================================================================================== // Draws a JPEG using QuickTime. //===================================================================================== static OSErr DrawJPEGQuickTime(Handle theHandle, JVDrawParamsHandle theParams) { PixMapHandle dPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); NestedProgress theProgress = (*theParams)->progress; long theSize = GetHandleSize(theHandle); Rect srcRect = (*theParams)->bounds; char hState = HGetState(theHandle); ImageDescriptionHandle theDesc; MatrixRecord theMatrix; OSErr theErr; KeepSpinning(); if (theDesc = (ImageDescriptionHandle)AnyNewHandle(sizeof(ImageDescription))) { HLock((Handle)theDesc); theErr = MakeJPEGImageDesc(theHandle, theDesc); if (theErr == noErr) { SetIdentityMatrix(&theMatrix); HLock(theHandle); FixBits((CGrafPtr)qd.thePort, true); KeepSpinning(); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon); InstallQDxDispatchPatch(true); theErr = FDecompressImage(StripAddress(*theHandle), theDesc, dPixMap, &srcRect, &theMatrix, srcCopy, qd.thePort->visRgn, nil, nil, codecHighQuality, anyCodec, theSize, nil, (ICMProgressProcRecordPtr)&theProgress); RemoveQDxDispatchPatch(); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon); if ((*theParams)->progress.aborted) theErr = codecAbortErr; KeepSpinning(); FixBits((CGrafPtr)qd.thePort, false); HSetState(theHandle, hState); } DisposeHandle((Handle)theDesc); } else gIntError = errNoDrawMemory, theErr = memFullErr; return theErr; } //===================================================================================== // OSErr FixJPEG(ImageHandle theImage, Handle *finalData, Boolean palette) //===================================================================================== // "Fixes" an image so that it can be saved as a JFIF. Basically, we convert any PICTs // to JFIF format, and save the quantized palette out to a global handle for later use // by the saving routine. //===================================================================================== extern OSErr FixJPEG(ImageHandle theImage, Handle *finalData, Boolean palette) { OSErr theErr = noErr; if ((*theImage)->format->inType != kPICTType && (*theImage)->format->inType != kSCRNType && (*theImage)->format->inType != kJPEGType) return errAETypeError; if ((*theImage)->format->inType == kPICTType || (*theImage)->format->inType == kSCRNType) { KeepSpinning(); if (!(*finalData = UnwrapJPEG((*theImage)->data))) return memFullErr; } else *finalData = (*theImage)->data; if (palette) { if (gJFIFColors = (CTabHandle)NewHandle(4)) Palette2CTab((*theImage)->qpalette, gJFIFColors); else return memFullErr; } else gJFIFColors = nil; return theErr; } //===================================================================================== // OSErr SaveJPEG(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, // Rect *theRect, Handle privates) //===================================================================================== // Saves a JFIF image out to disk, including the preview image and palette resource, // if specified. //===================================================================================== extern OSErr SaveJPEG(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle privates) { #if applec #pragma unused(privates) #endif long theSize = GetHandleSize(theHandle); uchar *headerStart, *headerEnd, *theAdr; char hState = HGetState(theHandle); short theFile; OSErr theErr; long theLen; KeepSpinning(); theAdr = (uchar *)(*theHandle); if ((headerStart = GetJPEGData(theAdr, theSize, 0xe0)) && headerStart[0] == 'J' && headerStart[1] == 'F' && headerStart[2] == 'I' && headerStart[3] == 'F' && headerStart[4] == 0) { headerStart -= 4; headerEnd = headerStart + (headerStart[2] << 8) + headerStart[3] + 2; while (headerEnd[1] == 0xe0 && headerEnd[4] == 'J' && headerEnd[5] == 'F' && headerEnd[6] == 'X' && headerEnd[7] == 'X' && headerEnd[8] == 0) headerEnd += (headerEnd[2] << 8) + headerEnd[3] + 2; } else if (headerStart = GetJPEGData(theAdr, theSize, 0xd8)) { headerStart -= 2; headerEnd = headerStart; } else return gIntError = errCorruptImage, codecBadDataErr; HLock(theHandle); KeepSpinning(); theErr = FSpCreate(theSpec, kCreator, kJPEGType, 0); if (theErr == noErr) { KeepSpinning(); theErr = FSpOpenDF(theSpec, fsWrPerm, &theFile); if (theErr == noErr) { KeepSpinning(); theLen = (long)(headerStart - theAdr); theErr = FSWrite(theFile, &theLen, theAdr); if (theErr == noErr) { KeepSpinning(); theSize -= theLen; theErr = WriteJFIFHeader(theFile, thePreview, theRect); if (theErr == noErr) { SpinIndef(); theSize -= (long)(headerEnd - headerStart); theErr = FSWrite(theFile, &theSize, headerEnd); KeepSpinning(); if (theErr == noErr) { FSClose(theFile); HSetState(theHandle, hState); if (gJFIFColors) { FSpCreateResFile(theSpec, kCreator, kJPEGType, 0); if (theFile = FSpOpenResFile(theSpec, fsRdWrPerm)) { AddResource((Handle)gJFIFColors, 'clut', 0, gNullString); if ((theErr = ResError()) == noErr) { WriteResource((Handle)gJFIFColors); ReleaseResource((Handle)gJFIFColors); } else theErr = ResError(), gIntError = errCantWriteFile; CloseResFile(theFile); } else theErr = ResError(), gIntError = errCantWriteFile; if (theErr != noErr) DisposeHandle((Handle)gJFIFColors); } return theErr; } else gIntError = errCantWriteFile; } } else gIntError = errCantWriteFile; FSClose(theFile); } else gIntError = errCantOpenFile; FSpDelete(theSpec); } else gIntError = errCantCreateFile; HSetState(theHandle, hState); if (theErr != noErr && gJFIFColors) DisposeHandle((Handle)gJFIFColors); return theErr; } //===================================================================================== // void InitJPEGUPPs(void) //===================================================================================== // Initializes all the local UPPs for the JPEG callbacks. //===================================================================================== static void InitJPEGUPPs(void) { gUnwrapPixProc = NewStdPixProc((ProcPtr)UnwrapPixProc); gDummyBitsProc = NewQDBitsProc((ProcPtr)DummyBitsProc); gDummyTextProc = NewQDTextProc((ProcPtr)DummyTextProc); gDummyLineProc = NewQDLineProc((ProcPtr)DummyLineProc); gDummyRectProc = NewQDRectProc((ProcPtr)DummyRectProc); gDummyRRectProc = NewQDRRectProc((ProcPtr)DummyRRectProc); gDummyOvalProc = NewQDOvalProc((ProcPtr)DummyOvalProc); gDummyArcProc = NewQDArcProc((ProcPtr)DummyArcProc); gDummyPolyProc = NewQDPolyProc((ProcPtr)DummyPolyProc); gDummyRgnProc = NewQDRgnProc((ProcPtr)DummyRgnProc); } //===================================================================================== // uchar *GetJPEGData(uchar *theAdr, long theLen, uchar theCode) //===================================================================================== // Returns the address of the specified marker within the JPEG data stream. //===================================================================================== static uchar *GetJPEGData(uchar *theAdr, long theLen, uchar theCode) { uchar *theEnd = theAdr + theLen; long theSize; while (true) { while (*theAdr++ != 0xff && theAdr < theEnd); if (theAdr >= theEnd) return nil; while (*theAdr == 0xff) theAdr++; if (theAdr >= theEnd) return nil; if (*theAdr == theCode) break; else if (*theAdr == 0xd9) return nil; else if (*theAdr <= 0x01 || (*theAdr >= 0xd0 && *theAdr <= 0xd8)) { theAdr++; continue; } theAdr++; if ((theSize = (*theAdr << 8) + *(theAdr + 1)) < 0) return nil; if ((theAdr + theSize) >= theEnd) { *(theAdr - 1) = 0xd9; return nil; } else theAdr += theSize; } theAdr += 3; return theAdr; } //===================================================================================== // void GetJPEGInfo(ImageHandle theImage) //===================================================================================== // Examines the quantization tables, counts the number of components, and estimates a // quality factor for IJG-compatible JPEGs. //===================================================================================== static void GetJPEGInfo(ImageHandle theImage) { Boolean isApple = false, isAdobe = false, isIJG = true; Handle theHandle = (*theImage)->data; long theLen = GetHandleSize(theHandle), theQuality = 0, len; short components = 0; uchar *theData; ushort theID; if (theData = GetJPEGData((uchar *)*theHandle, theLen, 0xfe)) { isApple = (theData[0] == 'A' && theData[1] == 'p' && theData[2] == 'p' && theData[3] == 'l' && theData[4] == 'e' && theData[5] == 'M'); } else if (theData = GetJPEGData((uchar *)*theHandle, theLen, 0xee)) { if (theData[0] == 'A' && theData[1] == 'd' && theData[2] == 'o' && theData[3] == 'b' && theData[4] == 'e' && theData[5] == 0) isAdobe = true; } (*theImage)->desc.spatialQuality = 0; BlockMove(gString[strUnknownJPEG], (*theImage)->desc.name, *gString[strUnknownJPEG] + 1); if (!(theData = GetJPEGData((uchar *)*theHandle, theLen, 0xdb))) return; do { len = ((long)theData[-2] << 8) + theData[-1] - 2; while (len > 0) { theID = *theData++; len--; if (isApple) CalcAppleTable(theID, theData, &theQuality); else if (isAdobe || !CalcIJGTable(theID, theData, &theQuality)) isIJG = false; if (theID >> 4) { theData += 128; len -= 128; } else { theData += 64; len -= 64; } components++; } theLen = StripAddress(*theHandle) + GetHandleSize(theHandle) - StripAddress(theData); } while (theData = GetJPEGData(theData, theLen, 0xdb)); if (isApple) { BlockMove(gString[strQuickTimeJPEG], (*theImage)->desc.name, *gString[strQuickTimeJPEG] + 1); } else if (isAdobe) { BlockMove(gString[strAdobeJPEG], (*theImage)->desc.name, *gString[strAdobeJPEG] + 1); } else if (isIJG) { (*theImage)->desc.spatialQuality = ((theQuality + 0x7fff) / components) >> 16; BlockMove(gString[strIJGJPEG], (*theImage)->desc.name, *gString[strIJGJPEG] + 1); } } //===================================================================================== // Boolean CalcIJGTable(ushort theID, uchar *theData, long *theQuality) //===================================================================================== // Calculates the image quality for an IJG image. //===================================================================================== static Boolean CalcIJGTable(ushort theID, uchar *theData, long *theQuality) { long scaleFactor = 0, stdDev = 0; ushort *theTable, entry; register long val; if ((theID & 0xf) == 0) theTable = gIJGLumiTab; else if ((theID & 0xf) == 1) theTable = gIJGChromTab; else return false; for (entry = 0; entry < 64; entry++) { if (theID >> 4) { val = (theData[0] << 8) + theData[1]; theData += 2; } else val = *theData++; val *= 0x6400L / (long)*theTable++; scaleFactor += val; stdDev += (val >> 4) * (val >> 4); } scaleFactor >>= 6; stdDev >>= 6; stdDev -= (scaleFactor >> 4) * (scaleFactor >> 4); if (stdDev > 0x400) return false; if (scaleFactor <= 0x6400) *theQuality += ((0xc800 - scaleFactor) >> 1) << 8; else *theQuality += ((5000 << 16) / scaleFactor) << 8; return true; } //===================================================================================== // Boolean CalcAppleTable(ushort theID, uchar *theData, long *theQuality) //===================================================================================== // Calculates the image quality for an Apple JPEG image (not really, but in theory). //===================================================================================== static Boolean CalcAppleTable(ushort theID, uchar *theData, long *theQuality) { #if applec #pragma unused(theID, theData, theQuality) #endif return true; } //===================================================================================== // void ExtractComments(Ptr theJPEG, long origLen, Handle *theComments) //===================================================================================== // Finds any comments records in the JPEG data stream. //===================================================================================== extern void ExtractComments(Ptr theJPEG, long origLen, Handle *theComments) { long len, i, weird, theLen = origLen; uchar *theData; Boolean bad; theData = (uchar *)theJPEG; while (true) { if (!(theData = GetJPEGData(theData, theLen, 0xfe))) break; len = ((long)theData[-2] << 8) + theData[-1] - 2; bad = false; if (theData[0] == 'A' && theData[1] == 'p' && theData[2] == 'p' && theData[3] == 'l' && theData[4] == 'e' && theData[5] == 'M') bad = true; for (weird = i = 0; i < len && !bad; i++) { if (theData[i] >= 0x20 && theData[i] <= 0x7f) continue; else if (theData[i] == 0x0a) theData[i] = 0x0d; else if (theData[i] == 0x0d && theData[i + 1] == 0x0a) theData[++i] = 0x00; else weird++; } if (!bad) bad = (weird > (len >> 4)); if (bad) break; if (!*theComments) PtrToHand(theData, theComments, len); else PtrAndHand(theData, *theComments, len); theData += len; theLen = StripAddress(theJPEG) + origLen - StripAddress(theData); } } //===================================================================================== // OSErr CompressJFIFPreview(PixMapHandle thePixMap, Rect *theRect, // Handle *theHandle) //===================================================================================== // Compresses the JFIF preview using high quality JPEG. //===================================================================================== static OSErr CompressJFIFPreview(PixMapHandle thePixMap, Rect *theRect, Handle *theHandle) { char pixState = GetPixelsState(thePixMap); ImageDescriptionHandle theDesc; long theSize, removeSize = 0; OSErr theErr = noErr; uchar *theData; if (theDesc = (ImageDescriptionHandle)CheckedNewHandle(sizeof(ImageDescription), true)) { theErr = GetMaxCompressionSize(thePixMap, theRect, 32, codecHighQuality, kJPEGCompression, anyCodec, &theSize); if (theErr == noErr) *theHandle = CheckedNewHandle(theSize, true); if (*theHandle) { LockPixels(thePixMap); HLock(*theHandle); theErr = CompressImage(thePixMap, theRect, codecHighQuality, kJPEGCompression, theDesc, StripAddress(**theHandle)); HUnlock(*theHandle); SetPixelsState(thePixMap, pixState); if (theErr == noErr) { theSize = (*theDesc)->dataSize; theData = GetJPEGData((uchar *)**theHandle, theSize, 0xe0); if (theData && theData[0] == 'J' && theData[1] == 'F' && theData[2] == 'I' && theData[3] == 'F' && theData[4] == 0) { theData -= 4; removeSize = (theData[2] << 8) + theData[3] + 2; BlockMove(theData + removeSize, theData, theSize - removeSize); } SetHandleSize(*theHandle, theSize - removeSize); } else DisposeHandle(*theHandle), *theHandle = nil; } DisposeHandle((Handle)theDesc); } else theErr = memFullErr; return theErr; } //===================================================================================== // OSErr WriteJFIFHeader(short theFile, GWorldPtr thePreview, Rect *theRect) //===================================================================================== // Creates a new header for the active JPEG image and writes it to theFile. //===================================================================================== static OSErr WriteJFIFHeader(short theFile, GWorldPtr thePreview, Rect *theRect) { Handle theHandle, compressedPrev = nil; short width, height, h, w, rowSize; long theLen = 18, extLen = 0; uchar *bp, *pp, *rowStart; char mmuMode = true32b; OSErr theErr; if (thePreview) { if (gThePrefs.compressPrev) { PixMapHandle dstPixMap = GetGWorldPixMap(thePreview); LockPixels(dstPixMap); theErr = CompressJFIFPreview(dstPixMap, theRect, &compressedPrev); UnlockPixels(dstPixMap); } if (!compressedPrev) { width = Width(theRect); height = Height(theRect); theLen += 3 * width * height; } else extLen += GetHandleSize(compressedPrev) + 10; } if (!(theHandle = CheckedNewHandle(theLen + extLen, true))) return gIntError = errNoSaveMemory, memFullErr; HLock(theHandle); bp = (uchar *)StripAddress(*theHandle); *bp++ = 0xff; *bp++ = 0xe0; // JFIF Header *bp++ = (theLen - 2) >> 8; // Length of block *bp++ = (theLen - 2) & 0xff; *bp++ = 'J'; *bp++ = 'F'; // JFIF signature *bp++ = 'I'; *bp++ = 'F'; *bp++ = 0x00; *bp++ = 0x01; *bp++ = (compressedPrev) ? 0x02 : 0x01; // Version number = 1.01/02 *bp++ = 0x00; // Units = none *bp++ = 0x00; *bp++ = 0x01; // Horizontal resolution *bp++ = 0x00; *bp++ = 0x01; // Vertical resolution if (thePreview && !compressedPrev) { PixMapHandle thePixMap = GetGWorldPixMap(thePreview); *bp++ = width; // Width of preview image *bp++ = height; // Height of preview image LockPixels(thePixMap); rowStart = (uchar *)GetPixBaseAddr(thePixMap); rowSize = (*thePixMap)->rowBytes & 0x3fff; SwapMMUMode(&mmuMode); for (h = 0; h < height; h++) { pp = rowStart; for (w = 0; w < width; w++) { pp++; *bp++ = *pp++; *bp++ = *pp++; *bp++ = *pp++; } rowStart += rowSize; } SwapMMUMode(&mmuMode); UnlockPixels(thePixMap); } else { *bp++ = 0x00; *bp++ = 0x00; // Width and height of preview image = 0 } if (compressedPrev) { *bp++ = 0xff; *bp++ = 0xe0; // APP0 marker *bp++ = (extLen - 2) >> 8; // Length of block *bp++ = (extLen - 2) & 0xff; *bp++ = 'J'; *bp++ = 'F'; // JFXX signature *bp++ = 'X'; *bp++ = 'X'; *bp++ = 0x00; *bp++ = 0x10; // JPEG-coded preview extension BlockMove(*compressedPrev, bp, GetHandleSize(compressedPrev)); DisposeHandle(compressedPrev); } KeepSpinning(); theLen += extLen; theErr = FSWrite(theFile, &theLen, *theHandle); KeepSpinning(); if (theErr != noErr) gIntError = errCantWriteFile; DisposeHandle(theHandle); return theErr; } //===================================================================================== // OSErr MakeJPEGImageDesc(Handle theHandle, ImageDescriptionHandle theDesc) //===================================================================================== // Creates a QuickTime image description record based on JPEG data. //===================================================================================== static OSErr MakeJPEGImageDesc(Handle theHandle, ImageDescriptionHandle theDesc) { long theLen = GetHandleSize(theHandle); uchar *theData; short theCode; for (theCode = 0xc0; theCode < 0xd0; theCode++) if (theData = GetJPEGData((uchar *)*theHandle, theLen, theCode)) break; if (theCode == 0xd0) return gIntError = errCorruptImage, codecBadDataErr; (*theDesc)->idSize = sizeof(ImageDescription); (*theDesc)->cType = kJPEGCompression; (*theDesc)->resvd1 = (*theDesc)->resvd2 = (*theDesc)->dataRefIndex = 0; BlockMove(gJPEGInfo.typeName, (*theDesc)->name, 32); (*theDesc)->version = gJPEGInfo.version; (*theDesc)->revisionLevel = gJPEGInfo.revisionLevel; (*theDesc)->vendor = gJPEGInfo.vendor; (*theDesc)->temporalQuality = 0; (*theDesc)->spatialQuality = 0x200L; (*theDesc)->width = (theData[3] << 8) + theData[4]; (*theDesc)->height = (theData[1] << 8) + theData[2]; (*theDesc)->hRes = (*theDesc)->vRes = 0x480000L; (*theDesc)->dataSize = theLen; (*theDesc)->frameCount = 1; (*theDesc)->depth = 32; (*theDesc)->clutID = -1; return noErr; } //===================================================================================== // Handle UnwrapJPEG(Handle srcHandle) //===================================================================================== // Extracts (unwraps) the original JPEG data from a JPEG PICT image. //===================================================================================== extern Handle UnwrapJPEG(Handle srcHandle) { long theSize = GetHandleSize(srcHandle); char hState = HGetState(srcHandle); CQDProcs theProcs, *oldProcs; KeepSpinning(); if (MakeMemAvailable(theSize) && (gJPEGDestHandle = NewHandle(theSize))) { HLockHi(srcHandle); PushPort(); MySetPort(gGenericGWorld); SetStdCProcs(&theProcs); if (!gUnwrapPixProc) InitJPEGUPPs(); theProcs.newProc1 = (UniversalProcPtr)gUnwrapPixProc; theProcs.bitsProc = gDummyBitsProc; theProcs.textProc = gDummyTextProc; theProcs.lineProc = gDummyLineProc; theProcs.rectProc = gDummyRectProc; theProcs.rRectProc = gDummyRRectProc; theProcs.ovalProc = gDummyOvalProc; theProcs.arcProc = gDummyArcProc; theProcs.polyProc = gDummyPolyProc; theProcs.rgnProc = gDummyRgnProc; oldProcs = gGenericGWorld->grafProcs; gGenericGWorld->grafProcs = &theProcs; KeepSpinning(); DrawTrimmedPicture((PicHandle)srcHandle, &(*(PicHandle)srcHandle)->picFrame, nil, false, nil); gGenericGWorld->grafProcs = oldProcs; PopPort(); HSetState(srcHandle, hState); return gJPEGDestHandle; } else gIntError = errNoUnwrapMemory; return nil; } //===================================================================================== // Handle UnwrapJPEG(Handle srcHandle) //===================================================================================== // Wraps a JPEG image into a PICT. //===================================================================================== extern Handle WrapJPEG(Handle srcHandle, short depth) { PixMapHandle thePixMap = GetGWorldPixMap(gGenericGWorld); long theSize = GetHandleSize(srcHandle); char hState = HGetState(srcHandle); ImageDescriptionHandle theDesc; OpenCPicParams theParams; Handle theHandle; OSErr theErr; KeepSpinning(); HLock(srcHandle); if (MakeMemAvailable(theSize) && (theDesc = (ImageDescriptionHandle)CheckedNewHandle(sizeof(ImageDescription), true))) { theErr = MakeJPEGImageDesc(srcHandle, theDesc); if (depth == 8 || depth == 40) (*theDesc)->depth = 40; if (theErr == noErr) { MySetRect(&theParams.srcRect, 0, 0, (*theDesc)->width, (*theDesc)->height); theParams.hRes = (*theDesc)->hRes; theParams.vRes = (*theDesc)->vRes; theParams.version = -2; theParams.reserved1 = theParams.reserved2 = 0; LockPixels(thePixMap); PushPort(); MySetPort(gGenericGWorld); ClipRect(&theParams.srcRect); if (theHandle = (Handle)OpenCPicture(&theParams)) { KeepSpinning(); theErr = FDecompressImage(StripAddress(*srcHandle), theDesc, thePixMap, &theParams.srcRect, nil, ditherCopy, nil, nil, nil, codecHighQuality, anyCodec, theSize, nil, nil); KeepSpinning(); UnlockPixels(thePixMap); ClosePicture(); if (theErr == noErr && !EmptyRect(&(*(PicHandle)theHandle)->picFrame)) { PopPort(); DisposeHandle((Handle)theDesc); HSetState(srcHandle, hState); return theHandle; } DisposeHandle(theHandle); } else gIntError = errNoWrapMemory; PopPort(); } DisposeHandle((Handle)theDesc); } else gIntError = errNoWrapMemory; HSetState(srcHandle, hState); return nil; } //===================================================================================== // pascal void UnwrapPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, // short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, // short callOldBits) //===================================================================================== // Bottleneck function called to extract raw JPEG data from an image. //===================================================================================== static pascal void UnwrapPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short callOldBits) { #if applec #pragma unused(srcRect, matrix, mode, mask, matte, matteRect, callOldBits) #endif long bufSize, left, offset = 0; ImageDescriptionHandle theDesc; ICMProgressProcRecord progProc; ICMDataProcRecord dataProc; Ptr theData, destAdr; KeepSpinning(); if (!GetCompressedPixMapInfo(src, &theDesc, &theData, &bufSize, &dataProc, &progProc)) { if ((*theDesc)->cType == kJPEGCompression) { HLock(gJPEGDestHandle); destAdr = (Ptr)*gJPEGDestHandle; left = (*theDesc)->dataSize; if (dataProc.dataProc) { while (left > bufSize) { BlockMove(theData, &destAdr[offset], bufSize); offset += bufSize; left -= bufSize; theData += bufSize; if (CallICMDataProc(dataProc.dataProc, &theData, (left > bufSize) ? bufSize : left, dataProc.dataRefCon)) return; } } BlockMove(theData, &destAdr[offset], left); HUnlock(gJPEGDestHandle); } } } //===================================================================================== // Dummy QuickDraw bottlenecks to filter out non-PixMaps within PICTs //===================================================================================== static pascal void DummyBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask) { #if applec #pragma unused(src, srcRect, dstRect, mode, mask) #endif } static pascal void DummyTextProc(short count, const void *textAddr, Point numer, Point denom) { #if applec #pragma unused(count, textAddr, numer, denom) #endif } static pascal void DummyLineProc(Point newPt) { #if applec #pragma unused(newPt) #endif } static pascal void DummyRectProc(GrafVerb verb, const Rect *r) { #if applec #pragma unused(verb, r) #endif } static pascal void DummyRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, short ovalHeight) { #if applec #pragma unused(verb, r, ovalWidth, ovalHeight) #endif } static pascal void DummyOvalProc(GrafVerb verb, const Rect *r) { #if applec #pragma unused(verb, r) #endif } static pascal void DummyArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle) { #if applec #pragma unused(verb, r, startAngle, arcAngle) #endif } static pascal void DummyPolyProc(GrafVerb verb, PolyHandle poly) { #if applec #pragma unused(verb, poly) #endif } static pascal void DummyRgnProc(GrafVerb verb, RgnHandle rgn) { #if applec #pragma unused(verb, rgn) #endif } \ No newline at end of file diff --git a/Source/C/JPEGNoQuickTime.c b/Source/C/JPEGNoQuickTime.c new file mode 100644 index 0000000..1cf6946 --- /dev/null +++ b/Source/C/JPEGNoQuickTime.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include #include #include #include "jpeglib.h" #include "jerror.h" #include "JPEGNoQuickTime.h" extern const char * const jpeg_message_table[]; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr DecompressJPEGImage(struct jpeg_decompress_struct *cinfo, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog); static CTabHandle MakeGrayscaleColorTable(void); static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow); GLOBAL void InitIJGSource (j_decompress_ptr cinfo, Handle theHandle); GLOBAL struct jpeg_error_mgr * InitIJGErrors (struct jpeg_error_mgr * err); static jmp_buf gJPEGErrorReturn; extern OSErr DrawJPEGNoQuickTime(Handle theHandle, JVDrawParamsHandle theParams) { NestedProgress theProgress = (*theParams)->progress; struct jpeg_decompress_struct cinfo; char hState = HGetState(theHandle); struct jpeg_error_mgr jerr; CTabHandle theColors = nil; GWorldPtr theGWorld = nil; OSErr theErr; if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon); HLock(theHandle); cinfo.err = InitIJGErrors(&jerr); theErr = setjmp(gJPEGErrorReturn); if (theErr == noErr) { jpeg_create_decompress(&cinfo); InitIJGSource(&cinfo, theHandle); theErr = setjmp(gJPEGErrorReturn); if (theErr == noErr) { jpeg_read_header(&cinfo, true); jpeg_start_decompress(&cinfo); if (cinfo.out_color_components == 1) theColors = MakeGrayscaleColorTable(); theGWorld = NewTempGWorld(cinfo.output_width, cinfo.output_height, (cinfo.out_color_components == 1) ? 8 : 32, theColors); if (cinfo.out_color_components == 1) DisposCTable(theColors); if (theGWorld) { theErr = DecompressJPEGImage(&cinfo, GetGWorldPixMap(theGWorld), (ICMProgressProcRecordPtr)&theProgress); if ((*theParams)->progress.aborted) theErr = codecAbortErr; } else gIntError = errNoDrawMemory, theErr = memFullErr; } /*if (theErr == noErr) { theErr = setjmp(gJPEGErrorReturn); if (theErr == noErr) jpeg_finish_decompress(&cinfo); }*/ jpeg_destroy_decompress(&cinfo); } if (theGWorld) DisposeGWorld(theGWorld); HSetState(theHandle, hState); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon); return theErr; } static OSErr DecompressJPEGImage(struct jpeg_decompress_struct *cinfo, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog) { char pState = GetPixelsState(dstPixMap); RgnHandle dstRgn = qd.thePort->visRgn; ulong bandRow = 0, row, bufferRows = Height(&(*dstPixMap)->bounds), total, count = 1, nextUpdate = 32; short lastLine = (*qd.thePort->visRgn)->rgnBBox.bottom; JSAMPARRAY scanLines = nil; OSErr theErr = noErr; uchar *rowStart; LockPixels(dstPixMap); theErr = setjmp(gJPEGErrorReturn); if (theErr == noErr) { rowStart = (uchar *)GetPixBaseAddr(dstPixMap); if (scanLines = (JSAMPARRAY)NewPtrClear(bufferRows * sizeof(JSAMPROW))) { for (row = 0; row < bufferRows; row++) scanLines[row] = rowStart, rowStart += (*dstPixMap)->rowBytes & 0x3fff; for (row = 0; row < lastLine && count && theErr == noErr; row += total) { total = 0; while (total < bufferRows && (row + total) < lastLine && theErr == noErr) { // note that we don't swap MMU mode here; we assume that since the GWorld was allocated // locally, it is always addressable through the current MMU state count = jpeg_read_scanlines(cinfo, &scanLines[total], bufferRows - total); if (!count) break; total += count; if ((row + total) > nextUpdate) { if (prog->progressProc) theErr = (OSErr)CallICMProgressProc(prog->progressProc, codecProgressUpdatePercent, FixRatio(row + total, lastLine), prog->progressRefCon); nextUpdate += 32; } } CopyPixMapToDestination(dstPixMap, row); } } } if (scanLines) DisposePtr((Ptr)scanLines); SetPixelsState(dstPixMap, pState); return theErr; } static CTabHandle MakeGrayscaleColorTable(void) { ushort color, count = 256, i; CTabHandle theColors; theColors = (CTabHandle)NewHandleClear(sizeof(ColorTable) + (count - 1) * sizeof(ColorSpec)); if (theColors) { (*theColors)->ctSeed = GetCTSeed(); (*theColors)->ctFlags = 0x8000; (*theColors)->ctSize = count - 1; for (i = 0; i < count; i++) { color = (ulong)i * 65535L / (long)(count - 1); (*theColors)->ctTable[i].rgb.red = (*theColors)->ctTable[i].rgb.green = (*theColors)->ctTable[i].rgb.blue = color; } } return theColors; } //===================================================================================== // void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) //===================================================================================== // Copies the band contained in srcPixMap to the destination, offset from the top by // startRow. //===================================================================================== static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) { Rect srcRect = (*srcPixMap)->bounds, dstRect = (*srcPixMap)->bounds; PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); char srcState = HGetState((Handle)srcPixMap); char dstState = HGetState((Handle)dstPixMap); OffsetRect(&dstRect, 0, startRow); if (dstRect.bottom > (*qd.thePort->visRgn)->rgnBBox.bottom) { srcRect.bottom -= dstRect.bottom - (*qd.thePort->visRgn)->rgnBBox.bottom; dstRect.bottom = (*qd.thePort->visRgn)->rgnBBox.bottom; } HLock((Handle)srcPixMap); HLock((Handle)dstPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &srcRect, &dstRect, srcCopy + ditherCopy, qd.thePort->visRgn); HSetState((Handle)dstPixMap, dstState); HSetState((Handle)srcPixMap, srcState); } //============================================================================================ //============================================================================================ //=========================== ================================== //=========================== IJG Data Source Object Code ================================== //=========================== ================================== //============================================================================================ //============================================================================================ /* Expanded data source object for stdio input */ typedef struct { struct jpeg_source_mgr pub; /* public fields */ } my_source_mgr; typedef my_source_mgr * my_src_ptr; /* * Initialize source --- called by jpeg_read_header * before any data is actually read. */ METHODDEF void init_source (j_decompress_ptr cinfo) { } /* * Fill the input buffer --- called whenever buffer is emptied. */ METHODDEF boolean fill_input_buffer (j_decompress_ptr cinfo) { static JOCTET dummyBuffer[] = { (JOCTET)0xff, (JOCTET)JPEG_EOI }; my_src_ptr src = (my_src_ptr) cinfo->src; WARNMS(cinfo, JWRN_JPEG_EOF); src->pub.next_input_byte = (JOCTET *)&dummyBuffer; src->pub.bytes_in_buffer = 2; return TRUE; } /* * Skip data --- used to skip over a potentially large amount of * uninteresting data (such as an APPn marker). */ METHODDEF void skip_input_data (j_decompress_ptr cinfo, long num_bytes) { my_src_ptr src = (my_src_ptr) cinfo->src; src->pub.next_input_byte += num_bytes; src->pub.bytes_in_buffer -= num_bytes; } /* * An additional method that can be provided by data source modules is the * resync_to_restart method for error recovery in the presence of RST markers. * For the moment, this source module just uses the default resync method * provided by the JPEG library. That method assumes that no backtracking * is possible. */ /* * Terminate source --- called by jpeg_finish_decompress * after all data has been read. Often a no-op. */ METHODDEF void term_source (j_decompress_ptr cinfo) { } /* * Prepare for input from a memory handle. */ GLOBAL void InitIJGSource (j_decompress_ptr cinfo, Handle theHandle) { my_src_ptr src; if (cinfo->src == NULL) { /* first time for this JPEG object? */ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr)); } src = (my_src_ptr) cinfo->src; src->pub.init_source = init_source; src->pub.fill_input_buffer = fill_input_buffer; src->pub.skip_input_data = skip_input_data; src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ src->pub.term_source = term_source; src->pub.bytes_in_buffer = GetHandleSize(theHandle); src->pub.next_input_byte = (JOCTET *)StripAddress(*theHandle); } //============================================================================================ //============================================================================================ //=========================== ================================== //=========================== IJG Error Object Code ================================== //=========================== ================================== //============================================================================================ //============================================================================================ /* * Error exit handler: must not return to caller. */ METHODDEF void error_exit (j_common_ptr cinfo) { (*cinfo->err->output_message) (cinfo); if (cinfo->err->msg_code == JERR_OUT_OF_MEMORY) { gIntError = errNoDrawMemory; longjmp(gJPEGErrorReturn, memFullErr); } else { longjmp(gJPEGErrorReturn, codecBadDataErr); } } /* * Actual output of an error or trace message. */ METHODDEF void output_message (j_common_ptr cinfo) { Str255 theString; short length; /* Create the message */ (*cinfo->err->format_message) (cinfo, (char *)theString); /* Display it in a dialog box */ if (!gDrawing || !Corrupt(gDrawing)) { length = strlen((char *)theString); BlockMove(theString, &theString[1], length); *theString = length; PushPort(); StringError(errJPEGError, theString); PopPort(); } } /* * Decide whether to emit a trace or warning message. * msg_level is one of: * -1: recoverable corrupt-data warning, may want to abort. * 0: important advisory messages (always display to user). * 1: first level of tracing detail. * 2,3,...: successively more detailed tracing messages. * An application might override this method if it wanted to abort on warnings * or change the policy about which messages to display. */ METHODDEF void emit_message (j_common_ptr cinfo, int msg_level) { struct jpeg_error_mgr * err = cinfo->err; #if NOWARNINGS if (msg_level < 0) { /* It's a warning message. Since corrupt files may generate many warnings, * the policy implemented here is to show only the first warning, * unless trace_level >= 3. */ if (err->num_warnings == 0 || err->trace_level >= 3) (*err->output_message) (cinfo); /* Always count warnings in num_warnings. */ err->num_warnings++; } else { /* It's a trace message. Show it if trace_level >= msg_level. */ if (err->trace_level >= msg_level) (*err->output_message) (cinfo); } #endif } /* * Format a message string for the most recent JPEG error or message. * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX * characters. Note that no '\n' character is added to the string. * Few applications should need to override this method. */ METHODDEF void format_message (j_common_ptr cinfo, char * buffer) { struct jpeg_error_mgr * err = cinfo->err; int msg_code = err->msg_code; const char * msgtext = NULL; const char * msgptr; char ch; boolean isstring; /* Look up message string in proper table */ if (msg_code > 0 && msg_code <= err->last_jpeg_message) { msgtext = err->jpeg_message_table[msg_code]; } else if (err->addon_message_table != NULL && msg_code >= err->first_addon_message && msg_code <= err->last_addon_message) { msgtext = err->addon_message_table[msg_code - err->first_addon_message]; } /* Defend against bogus message number */ if (msgtext == NULL) { err->msg_parm.i[0] = msg_code; msgtext = err->jpeg_message_table[0]; } /* Check for string parameter, as indicated by %s in the message text */ isstring = FALSE; msgptr = msgtext; while ((ch = *msgptr++) != '\0') { if (ch == '%') { if (*msgptr == 's') isstring = TRUE; break; } } /* Format the message into the passed buffer */ if (isstring) sprintf(buffer, msgtext, err->msg_parm.s); else sprintf(buffer, msgtext, err->msg_parm.i[0], err->msg_parm.i[1], err->msg_parm.i[2], err->msg_parm.i[3], err->msg_parm.i[4], err->msg_parm.i[5], err->msg_parm.i[6], err->msg_parm.i[7]); } /* * Reset error state variables at start of a new image. * This is called during compression startup to reset trace/error * processing to default state, without losing any application-specific * method pointers. An application might possibly want to override * this method if it has additional error processing state. */ METHODDEF void reset_error_mgr (j_common_ptr cinfo) { cinfo->err->num_warnings = 0; /* trace_level is not reset since it is an application-supplied parameter */ cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */ } /* * Fill in the standard error-handling methods in a jpeg_error_mgr object. * Typical call is: * struct jpeg_compress_struct cinfo; * struct jpeg_error_mgr err; * * cinfo.err = jpeg_std_error(&err); * after which the application may override some of the methods. */ GLOBAL struct jpeg_error_mgr * InitIJGErrors (struct jpeg_error_mgr * err) { err->error_exit = error_exit; err->emit_message = emit_message; err->output_message = output_message; err->format_message = format_message; err->reset_error_mgr = reset_error_mgr; err->trace_level = 0; /* default = no tracing */ err->num_warnings = 0; /* no warnings emitted yet */ err->msg_code = 0; /* may be useful as a flag for "no error" */ /* Initialize message table pointers */ err->jpeg_message_table = jpeg_message_table; err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1; err->addon_message_table = NULL; err->first_addon_message = 0; /* for safety */ err->last_addon_message = 0; return err; } \ No newline at end of file diff --git a/Source/C/JPEGView.c b/Source/C/JPEGView.c new file mode 100644 index 0000000..0cf10d0 --- /dev/null +++ b/Source/C/JPEGView.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // VBLRecord: structure containing information about cursors that we set during VBL //===================================================================================== typedef struct VBLRecord { VBLTask theTask; CursHandle spin[kNumCursors]; ulong curSpin, lastSpin; Boolean spinning; } VBLRecord, *VBLRecordPtr; //===================================================================================== // Global variables local to this module //===================================================================================== static VBLRecord gVBLTask; static VBLUPP gSpinCursor; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static void MemoryInit(void); static void UPPInit(void); static void ToolBoxInit(void); static void CheckSystem(void); static Boolean TrapAvailable(short theTrap); static void PaletteInit(void); static void GeneralInit(void); #if USESROUTINEDESCRIPTORS static pascal void SpinCursor(VBLTaskPtr theTask); #else static pascal void SpinCursor(void); #endif static void ErrorHandler(short theErr, short resID, StringPtr addString); //===================================================================================== // Set compiler up to turn off 68020 code generation for these first few functions, // until we're sure we're in a safe environment. //===================================================================================== #if THINK_C #pragma options(!mc68020) #elif applec #pragma processor 68000 #elif __MWERKS__ #pragma code68020 off #endif //===================================================================================== // void main(void) //===================================================================================== // Initialize the application, open any previously open floating windows, then start // the main event loop and wait until it's done before cleaning up. //===================================================================================== // NOTE: This needs to be compiled compatible for 68000-based machines, since we can't // be sure yet that we're on a 68020. //===================================================================================== extern void main(void) { Boolean statsOpen, commentsOpen, colorsOpen; // initialize everything gTitleBarHeight = kTitleBarHeight; MemoryInit(); AppleEventInit(); MonitorInit(); MenuBarInit(); DrawingInit(); PaletteInit(); GeneralInit(); gThePrefs.reminderCount++; // open any windoids that were left open from last run if (gThePrefs.statsOpen) if (OpenStats() == noErr && !gInBackground) ChangeActive(GetStatWindow()); if (gThePrefs.commentsOpen) { gCommentsOpen = true; if (OpenComments() == noErr && !gInBackground) ChangeActive(GetCommentsWindow()); } if (gThePrefs.colorsOpen) if (OpenColors() == noErr && !gInBackground) ChangeActive(GetColorsWindow()); // set up the menus and take our events AdjustMenus(); MainEventLoop(); // close all the open windows, one at a time statsOpen = gThePrefs.statsOpen; commentsOpen = gThePrefs.commentsOpen; colorsOpen = gThePrefs.colorsOpen; while (FrontWindow()) DoCloseWindow(FrontWindow(), false); // save the preferences, reset devices, and exit gThePrefs.statsOpen = statsOpen; gThePrefs.commentsOpen = commentsOpen; gThePrefs.colorsOpen = colorsOpen; SaveGeneralPrefs(); ResetDevices(); if (GetFirstWindow()) CalcVisBehind((WindowPeek)GetFirstWindow(), GetGrayRgn()); RemoveQDxDispatchPatch(); MySetPort(nil); HiliteMenu(0); ExitToShell(); } //===================================================================================== // void MemoryInit(void) //===================================================================================== // Set up the application, call the main event loop, then clean up when done. //===================================================================================== // NOTE: This needs to be compiled compatible for 68000-based machines, since we can't // be sure yet that we're on a 68020. //===================================================================================== static void MemoryInit(void) { Handle tempHandle; Str255 theString; short i; // increase the stack size SetApplLimit(GetApplLimit() - kStackSize); MaxApplZone(); for (i = 0; i < 24; i++) MoreMasters(); // set up all our callback function UPP's UPPInit(); // start up the Toolbox now ToolBoxInit(); // verify the system configuration CheckSystem(); // set the grow zone procedure SetGrowZone(NewGrowZoneProc((ProcPtr)GrowZone)); // allocate memory for windows & ports if (!(tempHandle = NewHandleClear(kMaxPorts * sizeof(DialogRecord)))) FatalError(errNoMemory); MoveHHi(tempHandle), HLock(tempHandle); gPortPool = (DialogRecord *)StripAddress(*tempHandle); // load up all the JPEGView strings for (i = 1; i <= strLast; i++) { GetIndString(theString, rStrings, i); if (!theString[0]) FatalError(errNoLoadStrings); if (!(gString[i - 1] = (StringPtr)NewPtr(theString[0] + 1))) FatalError(errNoMemory); BlockMove(theString, gString[i - 1], theString[0] + 1); } for (i = 1; i <= kFileFormats; i++) { GetIndString(gFormat[i - 1]->formatName, rFormatNames, i); if (!gFormat[i - 1]->formatName) FatalError(errNoLoadStrings); } // load in all our custom cursors for (i = 0; i < kNumCursors; i++) { if (!(gVBLTask.spin[i] = GetCursor(rFirstSpin + i))) FatalError(errNoLoadCursor); MoveHHi((Handle)gVBLTask.spin[i]), HLock((Handle)gVBLTask.spin[i]); } StartSpinning(); if (!(gCross = GetCursor(crossCursor))) FatalError(errNoLoadCursor); MoveHHi((Handle)gCross), HLock((Handle)gCross); if (!(gHand = GetCursor(rHandCursor))) FatalError(errNoLoadCursor); MoveHHi((Handle)gCross), HLock((Handle)gHand); if (!(gSize = GetCursor(rSizeCursor))) FatalError(errNoLoadCursor); MoveHHi((Handle)gCross), HLock((Handle)gSize); } //===================================================================================== // void UPPInit(void) //===================================================================================== // Initializes all the global Universal Proc Pointers, for PowerPC compatibility. //===================================================================================== // NOTE: This needs to be compiled compatible for 68000-based machines, since we can't // be sure yet that we're on a 68020. //===================================================================================== static void UPPInit(void) { // from AppleEventUtils.c gAEIdleProc = NewAEIdleProc((ProcPtr)AEIdleProc); // from DialogUtils.c gGenericFilter = NewModalFilterProc((ProcPtr)GenericFilter); gOutlineOK = NewUserItemProc((ProcPtr)OutlineOK); gPopUpMenuBox = NewUserItemProc((ProcPtr)PopUpMenuBox); gLineItem = NewUserItemProc((ProcPtr)LineItem); // from FileMenu.c gOpenSaveModalFilter = NewModalFilterYDProc((ProcPtr)OpenSaveModalFilter); // from JPEGView.c gSpinCursor = NewVBLProc((ProcPtr)SpinCursor); // from ProgressProcs.c gDummyProg.prog.progressProc = NewICMProgressProc((ProcPtr)DummyProgress); gDummyProg.prog.progressRefCon = (long)&gDummyProg; gGenericProgress = NewICMProgressProc((ProcPtr)GenericProgress); gSlideProgress = NewICMProgressProc((ProcPtr)SlideProgress); gDrawProgress = NewICMProgressProc((ProcPtr)DrawProgress); } //===================================================================================== // void ToolBoxInit(void) //===================================================================================== // Initialize the toolbox manager and get the cursors. //===================================================================================== // NOTE: This needs to be compiled compatible for 68000-based machines, since we can't // be sure yet that we're on a 68020. //===================================================================================== static void ToolBoxInit(void) { // initialize the Toolbox here InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); #if !defined(powerc) && !defined(__powerc) { Handle h; short i; SetResLoad(false); for (i = Count1Resources('CODE'); i > 0; i--) { h = Get1IndResource('CODE', i); if (*h) HLock(h); else { LoadResource(h); if (ResError()) { SetResLoad(1); FatalError(errNoMemory); } else { HUnlock(h); MoveHHi(h); HLock(h); } } } SetResLoad (true) ; } #endif } //===================================================================================== // Boolean TrapAvailable(short theTrap) //===================================================================================== // Verifies if a trap is available to be called; swiped from THINK Reference with minor // changes. //===================================================================================== // NOTE: This needs to be compiled compatible for 68000-based machines, since we can't // be sure yet that we're on a 68020. //===================================================================================== static Boolean TrapAvailable(short theTrap) { short numToolboxTraps = 0x400; TrapType tType; tType = ((theTrap & 0x800) > 0) ? ToolTrap : OSTrap; if (tType == ToolTrap) theTrap &= 0x7ff; if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xaa6e, ToolTrap)) numToolboxTraps = 0x200; if (theTrap >= numToolboxTraps) return false; return (NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap)); } //===================================================================================== // void CheckSystem(void) //===================================================================================== // Check gestalt to be sure we have everything we need. //===================================================================================== // NOTE: This needs to be compiled compatible for 68000-based machines, since we can't // be sure yet that we're on a 68020. //===================================================================================== static void CheckSystem(void) { OSErr theErr; long resp; // die a quick death if not on 68020 if (!TrapAvailable(_Gestalt) || Gestalt(gestaltProcessorType, &resp) != noErr || resp < 3) { StopAlert(rNeeds68020Alert, nil); ExitToShell(); } // do the same if we're not running System 7 if (Gestalt(gestaltSystemVersion, &resp) != noErr || resp < 0x700) { StopAlert(rNeedsSystem7Alert, nil); ExitToShell(); } // verify QuickTime and image compression manager versions if (Gestalt(gestaltCompressionMgr, &resp) == noErr && resp >= 15) { if (Gestalt(gestaltQuickTime, &resp) == noErr) { if ((gQTVersion = resp >> 16) < 0x100) MinorError(errFunnyQTVersion); if (GetCodecInfo(&gJPEGInfo, kJPEGCompression, anyCodec) != noErr) gQTVersion = 0; #if defined(powerc) || defined(__powerc) if ((Ptr)DecompressImage == kUnresolvedSymbolAddress) gQTVersion = 0; #endif } } KeepSpinning(); MySetPort(nil); // see if the Drag Manager is present if (Gestalt(gestaltDragMgrAttr, &resp) == noErr && (resp & (1L << gestaltDragMgrPresent))) { gDragMgrPresent = true; #if defined(powerc) || defined(__powerc) if ((Ptr)InstallTrackingHandler == kUnresolvedSymbolAddress) gDragMgrPresent = false; #endif } // load the JPEGView icon family theErr = GetIconSuite(&gIconSuite, rAPPLType, svAllAvailableData); if (theErr != noErr) FatalError(errNoMemory); HNoPurge(gIconSuite); // set up our notification mgr item gTheNotification.qType = nmType; gTheNotification.nmMark = 1; // put diamond in application menu gTheNotification.nmIcon = gIconSuite; // flashing icon handle gTheNotification.nmSound = (Handle)-1; // system beep sound gTheNotification.nmStr = nil; // no alert box gTheNotification.nmResp = nil; // no response procedure gTheNotification.nmRefCon = 0; // no ref con } //===================================================================================== // Reset compiler to generate 68020 code again. //===================================================================================== #if THINK_C #pragma options(mc68020) #elif applec #pragma processor 68020 #elif __MWERKS__ #pragma code68020 off #endif //===================================================================================== // void PaletteInit(void) //===================================================================================== // Load up all the system color tables and convert them to palettes. //===================================================================================== static void PaletteInit(void) { CTabHandle theColors; short i; for (i = 1; i <= 8; i <<= 1) { if (theColors = GetCTable(64 + i)) { if (gColorPalette[i] = NewPalette(1 << i, theColors, pmTolerant, 0)) DisposCTable(theColors); else FatalError(errNoMemory); } else FatalError(errNoLoadCLUT); if (theColors = GetCTable(32 + i)) { if (gGreyPalette[i] = NewPalette(1 << i, theColors, pmTolerant, 0)) DisposCTable(theColors); else FatalError(errNoMemory); } else FatalError(errNoLoadCLUT); } KeepSpinning(); } //===================================================================================== // void GeneralInit(void) //===================================================================================== // Do the rest of the initialization. //===================================================================================== static void GeneralInit(void) { Rect prevRect = { 0, 0, 80, 80 }, iconRect = { 0, 0, 32, 32 }; ProcessSerialNumber thePSN, selfPSN = { 0, kCurrentProcess }; short refNum, oldRefNum = CurResFile(); ProcessInfoRec theInfo; EventRecord theEvent; Intl0Hndl intlData; FSSpec theSpec; OSErr theErr; ushort i; // find the JPEGView help file and open its resource fork theInfo.processAppSpec = &theSpec; theInfo.processInfoLength = sizeof(ProcessInfoRec); theInfo.processName = nil; theErr = GetProcessInformation(&selfPSN, &theInfo); if (theErr == noErr) { theErr = FSMakeFSSpec(theSpec.vRefNum, theSpec.parID, gString[strHelpFile], &theSpec); if (theErr == noErr) { refNum = FSpOpenResFile(&theSpec, fsRdPerm); UseResFile(oldRefNum); gHelpFound = true; } } // install and remove our QDxDispatch patch to force it to load InstallQDxDispatchPatch(false); RemoveQDxDispatchPatch(); // take a few events to let our background status become known for (i = 0; i < 4; i++) WaitNextEvent(mDownMask + keyDownMask + keyUpMask + autoKeyMask + updateMask + activMask, &theEvent, kSleepTime, nil); // determine our background status GetFrontProcess(&thePSN); SameProcess(&selfPSN, &thePSN, &gInBackground); gInBackground = !gInBackground; // initialize the slide show options if (LoadPrefsHandle(kPrefsSlideType, 0, (Handle *)&gSlideOptions) != noErr) if (PtrToHand((Ptr)&gDefaultSlideOptions, (Handle *)&gSlideOptions, sizeof(SlideOptions)) != noErr) FatalError(errNoMemory); // load the preferences LoadGeneralPrefs(); // create the preview and icon offscreen worlds if (!(gGenericGWorld = gPreviewGWorld = MyNewGWorld(&prevRect, 32, nil, nil, false, false)) || !(gIconGWorld = MyNewGWorld(&iconRect, 32, nil, nil, false, false))) FatalError(errNoMemory); // seed the random number generator qd.randSeed = TickCount(); KeepSpinning(); // get some international number info if (intlData = (Intl0Hndl)IUGetIntl(0)) { gThousandsSep = (*intlData)->thousSep; gDecimal = (*intlData)->decimalPt; gListSep = (*intlData)->listSep; } } //===================================================================================== // void StartSpinning(void) //===================================================================================== // Initialize the VBL task to begin spinning the cursor. //===================================================================================== extern void StartSpinning(void) { if (gVBLTask.spinning) return; gVBLTask.spinning = true; gVBLTask.curSpin %= kNumCursors; KeepSpinning(); gVBLTask.theTask.qType = vType; gVBLTask.theTask.vblAddr = gSpinCursor; gVBLTask.theTask.vblCount = kSpinContinue; gVBLTask.theTask.vblPhase = 0; SetCursor(*gVBLTask.spin[gVBLTask.curSpin]); VInstall((QElemPtr)&gVBLTask); } //===================================================================================== // void StopSpinning(CursPtr newCursor) //===================================================================================== // Remove the spinning task from the VBL queue. //===================================================================================== extern void StopSpinning(CursPtr newCursor) { if (gVBLTask.spinning) VRemove((QElemPtr)&gVBLTask); gVBLTask.spinning = false; SetCursor(newCursor); } //===================================================================================== // void KeepSpinning(void) //===================================================================================== // Keep the cursor spinning for another two cycles. //===================================================================================== extern void KeepSpinning(void) { gVBLTask.lastSpin = ((gVBLTask.curSpin / kNumCursors) + 2) * kNumCursors; } //===================================================================================== // void SpinIndef(void) //===================================================================================== // Keep the cursor spinning indefinitely. //===================================================================================== extern void SpinIndef(void) { gVBLTask.lastSpin = 0x7fffffff; } //===================================================================================== // pascal long GetVBLRec(void) //===================================================================================== // Some inline assembly to return the value in A0, which is a pointer to the VBLTask // record. //===================================================================================== // NOTE: This is only needed for the 680x0 version of the application; PowerPC versions // get the address of the VBLTask passed as a parameter, thanks to Apple's trickery. //===================================================================================== #if !USESROUTINEDESCRIPTORS static pascal long GetVBLRec(void) = 0x2e88; #endif //===================================================================================== // pascal void SpinCursor(void) //===================================================================================== // Actually spin the cursor; this is the VBL task function we point to. Note that we // absolutely must not move memory here. //===================================================================================== // NOTE: We use some conditional macros here to accomodate the nicer PowerPC version of // this function. //===================================================================================== #if USESROUTINEDESCRIPTORS static pascal void SpinCursor(VBLTaskPtr theTask) { VBLRecordPtr theData = (VBLRecordPtr)theTask; #else static pascal void SpinCursor(void) { VBLRecordPtr theData = (VBLRecordPtr)GetVBLRec(); #endif if (!LMGetCrsrBusy() && theData->curSpin < theData->lastSpin) SetCursor(*theData->spin[++theData->curSpin % kNumCursors]); theData->theTask.vblCount = kSpinFrequency; } //===================================================================================== // void HandleAEError(OSErr theErr, short memErr, StringPtr theString) //===================================================================================== // Handle an error returned from an apple event. //===================================================================================== extern void HandleAEError(OSErr theErr, short memErr, StringPtr theString) { if (gIntError) StringError(gIntError, theString); else switch (theErr) { case noErr: break; case errNoHelpFound: MinorError(theErr); break; case mFulErr: case memFullErr: if (memErr) StringError(memErr, theString); else MinorError(errNoMemory); break; case codecAbortErr: break; case codecBadDataErr: StringError(errCorruptImage, theString); break; case -4101: MinorError(errNoPrinterSelected); break; case iPrSavPFil: StringError(errCantPrint, theString); break; default: ErrorHandler(theErr, 0, gNullString); break; } gIntError = 0; } //===================================================================================== // void MinorError(short theErr) //===================================================================================== // Display an alert for a minor error. //===================================================================================== extern void MinorError(short theErr) { ErrorHandler(theErr, rMinorErrors, nil); } //===================================================================================== // void FatalError(short theErr) //===================================================================================== // Display an alert for a fatal error. //===================================================================================== extern void FatalError(short theErr) { ErrorHandler(theErr, rFatalErrors, nil); } //===================================================================================== // void StringError(short theErr, StringPtr origString) //===================================================================================== // Display an alert for a minor error that includes an inserted string. //===================================================================================== extern void StringError(short theErr, StringPtr origString) { Str255 theString; if (origString) { BlockMove(origString, theString, *origString + 1); ErrorHandler(theErr, rStringErrors, theString); } else ErrorHandler(theErr, rGenericStringErrors, nil); } //===================================================================================== // void ErrorHandler(short theErr, short resID, StringPtr addString) //===================================================================================== // Generic error handler. Note that we should post a notification manager event if // we're in the background. //===================================================================================== static void ErrorHandler(short theErr, short resID, StringPtr addString) { Boolean isFatal = (resID == rFatalErrors); Str255 theString; OSErr AEErr; // non-fatal errors in slide shows might need to be ignored if (!isFatal && gSlideShow && (*gSlideOptions)->noErrors) return; // any error during a screen saver slide show should return and abort if (gScreenSaver) { SendQuitApplication(); return; } // if we're in an Apple event, be polite and request to move to the front if (gInAppleEvent) { AEErr = AEInteractWithUser(kAEDefaultTimeout, &gTheNotification, gAEIdleProc); if (AEErr == errAENoUserInteraction) { if (isFatal) ExitToShell(); else return; } } // if we're in the background and it's not fatal, post a notification manager event if (gInBackground) RequestForeground(); // otherwise, display the appropriate alert with the appropriate text, if any MySetPort(nil); StopSpinning(&qd.arrow); if (resID) { GetIndString(theString, resID, theErr); if (theString[0]) { if (addString) ParamText(theString, addString, gNullString, gNullString); else ParamText(theString, gNullString, gNullString, gNullString); } else { ParamText((StringPtr)"\pCouldnÕt load the error messages!", gNullString, gNullString, gNullString); isFatal = true; } if (isFatal) { FWStopAlert(CenterAlert(rFatalAlert), nil); ExitToShell(); } else FWNoteAlert(CenterAlert(rMinorAlert), gGenericFilter); } else { NumToString(theErr, theString); ParamText(theString, gNullString, gNullString, gNullString); FWNoteAlert(CenterAlert(rUnknownAlert), gGenericFilter); } } //===================================================================================== // void RequestForeground(void) //===================================================================================== // Post a notifcation then sit in a loop, similar to the AppleEvent idle proc, and wait // until we get bumped to the foreground. //===================================================================================== extern void RequestForeground(void) { if (!gInBackground) return; NMInstall(&gTheNotification); while (gInBackground) { RgnHandle mouseRgn = nil; long sleep = kSleepTime; EventRecord theEvent; MySetPort((CGrafPtr)FWFrontWindow()); WaitNextEvent(activMask + updateMask + osMask + diskMask, &theEvent, sleep, mouseRgn); AEIdleProc(&theEvent, &sleep, &mouseRgn); } NMRemove(&gTheNotification); } \ No newline at end of file diff --git a/Source/C/JPEGViewEventHandlers.c b/Source/C/JPEGViewEventHandlers.c new file mode 100644 index 0000000..cbdf0ba --- /dev/null +++ b/Source/C/JPEGViewEventHandlers.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "JPEGViewEventHandlers.h" //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr DrawToDummyPort(ImageHandle theImage, Rect *srcRect, Rect *dstRect); static PicHandle MyOpenCPicture(Rect *dstRect, ImageHandle theImage); static Boolean WasDesktop(FSSpec *spec, Boolean recursive, ICMProgressProcRecordPtr theProg, OSErr *theErr); //===================================================================================== // pascal OSErr HandleQuantize(AppleEvent *theEvent, AppleEvent *reply, long refCon) //===================================================================================== // Handles the quantize image AppleEvent, from the JPEGView suite. //===================================================================================== extern pascal OSErr HandleQuantize(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(refCon) #endif ObjectTokenHandle theToken; PaletteHandle thePalette; CTabHandle theColors; ImageHandle theImage; OSErr theErr = noErr; AEDesc theObject; long numColors; AEBegin(); theErr = AEExtractObject(theEvent, keyDirectObject, &theObject); if (theErr == noErr) { theErr = AEExtractLong(theEvent, keyColorCount, &numColors); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if (theObject.descriptorType == cImage) { if ((*theToken)->count == 1) { theImage = FindImage((WindowPtr)(*theToken)->object[0]); StartSpinning(); theErr = DoQuantize(theImage, numColors, &thePalette, nil); StopSpinning(&qd.arrow); if (theErr == noErr) { if (theColors = (CTabHandle)NewHandle(4)) { Palette2CTab(thePalette, theColors); HLock((Handle)theColors); if (reply->dataHandle) theErr = AEPutParamPtr(reply, keyAEResult, typeColorTable, (void *)*theColors, GetHandleSize((Handle)theColors)); DisposeHandle((Handle)theColors); } else theErr = memFullErr; DisposePalette(thePalette); } } else theErr = errAENotASingleObject; } else theErr = errAECantHandleClass; } AEDisposeDesc(&theObject); } AEEnd(); return theErr; } //===================================================================================== // pascal OSErr HandleSlideShow(AppleEvent *theEvent, AppleEvent *reply, long refCon) //===================================================================================== // Handles the JPEGView slide show AppleEvent, from the JPEGView suite. //===================================================================================== extern pascal OSErr HandleSlideShow(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(reply, refCon) #endif long theLong, theCount, theIndex, actualSize; DescType theType, theKey; NestedProgress theProc = { { nil, 0 }, 0, 0L, 0L, false }; ICMProgressProcRecordPtr progPtr = (ICMProgressProcRecordPtr)&theProc; OSErr theErr = noErr; Boolean theBoolean; FSSpec theFile; AEDesc theList; theProc.prog.progressProc = gGenericProgress; theProc.prog.progressRefCon = (long)&theProc; if (gSlideShow) return noErr; AEBegin(); theErr = AEExtractLong(theEvent, keyDelay, &theLong); if (theErr == noErr) (*gSlideOptions)->delay = theLong; theErr = AEExtractBoolean(theEvent, keyFilenames, &theBoolean); if (theErr == noErr) (*gSlideOptions)->fileNames = theBoolean; theErr = AEExtractBoolean(theEvent, keyFromDisk, &theBoolean); if (theErr == noErr) (*gSlideOptions)->fromMemory = !theBoolean; theErr = AEExtractBoolean(theEvent, keyIgnoreErrors, &theBoolean); if (theErr == noErr) (*gSlideOptions)->noErrors = theBoolean; theErr = AEExtractBoolean(theEvent, keyImportFiles, &theBoolean); if (theErr == noErr) (*gSlideOptions)->allFiles = theBoolean; theErr = AEExtractBoolean(theEvent, keyRandom, &theBoolean); if (theErr == noErr) (*gSlideOptions)->random = theBoolean; theErr = AEExtractBoolean(theEvent, keyRepeat, &theBoolean); if (theErr == noErr) (*gSlideOptions)->repeat = theBoolean; theErr = AEExtractBoolean(theEvent, keyScanRecursive, &theBoolean); if (theErr == noErr) (*gSlideOptions)->recursive = theBoolean; theErr = AEExtractBoolean(theEvent, keyUserControl, &theBoolean); if (theErr == noErr) (*gSlideOptions)->userControl = theBoolean; theErr = AEExtractBoolean(theEvent, keyOffscreen, &theBoolean); if (theErr == noErr) (*gSlideOptions)->offscreen = theBoolean; theErr = AEExtractBoolean(theEvent, keyAutoComments, &theBoolean); if (theErr == noErr) (*gSlideOptions)->autoComments = theBoolean; theErr = AEExtractBoolean(theEvent, keyHideWindoids, &theBoolean); if (theErr == noErr) (*gSlideOptions)->hideWindoids = theBoolean; theErr = AEExtractBoolean(theEvent, keyHideControls, &theBoolean); if (theErr == noErr) (*gSlideOptions)->hideControls = theBoolean; theErr = AEExtractBoolean(theEvent, keyScreenSaver, &theBoolean); if (theErr == noErr) gScreenSaver = theBoolean; else gScreenSaver = false; if (gScreenSaver) gScreenSaverPoint = GlobalMouse(); theErr = AEGetParamDesc(theEvent, keyDirectObject, typeAEList, &theList); if (theErr == noErr) { if (!(*gSlideOptions)->fromMemory) { StartSpinning(); theErr = AECountItems(&theList, &theCount); if (theErr == noErr) { ParamText(gString[strScanningDirectory], gNullString, gNullString, gNullString); if (progPtr) CallICMProgressProc(progPtr->progressProc, codecProgressOpen, kIndefProgress, progPtr->progressRefCon); for (theIndex = 1; theIndex <= theCount; theIndex++) { if (theErr != noErr) break; theErr = AEGetNthPtr(&theList, theIndex, typeFSS, &theKey, &theType, (void *)&theFile, sizeof(FSSpec), &actualSize); if (theErr == noErr) { if (gScreenSaver) gSlideShow = true; if (!WasDesktop(&theFile, (*gSlideOptions)->recursive, progPtr, &theErr)) theErr = AddSlideDir(&theFile, (*gSlideOptions)->recursive, progPtr, nil); if (gScreenSaver) gSlideShow = false; } else theErr = errAEBadListItem; } if (progPtr) CallICMProgressProc(progPtr->progressProc, codecProgressClose, kIndefProgress, progPtr->progressRefCon); } else theErr = errAEWrongDataType; } if (theErr == noErr) { InitSlideShow(); gIntError = noErr; } else CleanUpSlideShow(); AEDisposeDesc(&theList); StopSpinning(&qd.arrow); } AEEnd(); return theErr; } //===================================================================================== // pascal OSErr HandleCopy(AppleEvent *theEvent, AppleEvent *reply, long refCon) //===================================================================================== // Handles the Copy AppleEvent, from the Miscellaneous Events suite. //===================================================================================== extern pascal OSErr HandleCopy(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(theEvent, reply, refCon) #endif OSErr theErr; AEBegin(); theErr = DoCopy(); AEEnd(); return theErr; } extern OSErr DoCopy(void) { ImageHandle theImage = FrontImage(); Boolean dontDispose = false; OSErr theErr = noErr; PicHandle thePict; if (theImage) { theErr = GetSelectedPICT(theImage, &thePict); if (theErr == noErr) { if (!thePict) { thePict = (PicHandle)(*theImage)->data; dontDispose = true; } ZeroScrap(); UnloadScrap(); HLock((Handle)thePict); PutScrap(GetHandleSize((Handle)thePict), kPICTType, StripAddress((Ptr)*thePict)); if (!dontDispose) DisposeHandle((Handle)thePict); } else if (theErr == codecAbortErr) theErr = noErr; } else theErr = errAEEventFailed; return theErr; } extern OSErr GetSelectedPICT(ImageHandle theImage, PicHandle *thePicture) { Rect srcRect, dstRect; OSErr theErr = noErr; CGrafPort dummyPort; if (AntsHaveSelection((*theImage)->ants)) SelRectToCropRect(theImage, &srcRect); else srcRect = (*theImage)->crect; if (EqualRect(&srcRect, &(*theImage)->grect) && (*theImage)->format->inType == kPICTType) { *thePicture = nil; return noErr; } dstRect = srcRect; OffsetRect(&dstRect, -dstRect.left, -dstRect.top); OpenCPort(&dummyPort); RectRgn(dummyPort.visRgn, &dstRect); ClipRect(&dstRect); PushPort(); MySetPort(&dummyPort); *thePicture = MyOpenCPicture(&dstRect, theImage); if (*thePicture) { theErr = DrawToDummyPort(theImage, &srcRect, &dstRect); ClosePicture(); if (!Width(&(**thePicture)->picFrame) && !Height(&(**thePicture)->picFrame)) theErr = memFullErr; if (theErr != noErr) DisposeHandle((Handle)*thePicture), *thePicture = nil; } else theErr = memFullErr; PopPort(); CloseCPort(&dummyPort); return theErr; } //===================================================================================== // PicHandle MyOpenCPicture(Rect *dstRect, ImageHandle theImage) //===================================================================================== // Opens up a color picture, in preparation for copying. We use a simple algorithm to // figure out whether to use application or temporary memory, in order to maximize the // likelihood that we'll be able to succeed. //===================================================================================== static PicHandle MyOpenCPicture(Rect *dstRect, ImageHandle theImage) { Size estSize = (((long)Height(&(*theImage)->grect) * (long)Width(&(*theImage)->grect) * (long)(*theImage)->depth) >> 3) * 3L / 4L; Size grow, tempMax = TempMaxMem(&grow), appMax = MaxMem(&grow); THz oldZone = GetZone(), tempZone; Boolean inTempMem = true; OpenCPicParams theParams; OSErr theErr = noErr; PicHandle thePict; // set up the OpenCPicture parameters theParams.srcRect = *dstRect; theParams.hRes = theParams.vRes = 0x480000L; theParams.version = -2; theParams.reserved1 = theParams.reserved2 = 0; // allocate a handle in temp memory, and retrieve the temporary zone from that thePict = (PicHandle)TempNewHandle(4, &theErr); if (thePict) { tempZone = HandleZone((Handle)thePict); DisposeHandle((Handle)thePict); } // some simple logic to determine if we should use app or temp memory if (!HasVirtualMemory() && (estSize < appMax || estSize > tempMax)) inTempMem = false; // open the picture if (inTempMem) SetZone(tempZone); thePict = OpenCPicture(&theParams); SetZone(oldZone); return thePict; } //===================================================================================== // OSErr DrawToDummyPort(ImageHandle theImage, Rect *srcRect, Rect *dstRect) //===================================================================================== // Actually does the drawing of the image to the dummy port. Of course, the dummy port // has been set up to bottleneck all the drawing into a picture, so nothing actually // gets drawn. //===================================================================================== static OSErr DrawToDummyPort(ImageHandle theImage, Rect *srcRect, Rect *dstRect) { NestedProgress progProc = { { nil, 0 }, 0, 0L, 0x10000L, false }; short oldBackgroundTime = gThePrefs.backgroundTime; Rect boundsRect = (*theImage)->grect; JVDrawParamsHandle theParams; OSErr theErr = noErr; progProc.prog.progressProc = gGenericProgress; // hack: Finder doesn't seem to like it if we give any apps time during // the drag process, so we force 0 sleep time and checking with // EventAvail gThePrefs.backgroundTime = bgMinimal; // allocate and initialize the drawing parameters if (theParams = NewDrawParams(&boundsRect, iqMedium, false, &progProc, (*theImage)->privateData)) { SetUpDrawPort(theParams, kOnscreenPort, (CGrafPtr)qd.thePort, srcRect, dstRect, false); // preflight the drawing here and save the port KeepSpinning(); theErr = PreflightDrawing(theParams); PushPort(); if (theErr == noErr) { // point to the dummy drawing port and start the inner progress proc MySetPort((*theParams)->dummy); UpdateParamText(gString[strCopying], gNullString, gNullString, (*theImage)->file.name); CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressOpen, 0L, (*theParams)->progress.prog.progressRefCon); // now do the drawing, either from the offscreen GWorld... if ((*theImage)->gworld && GWOrigSize(theImage)) CopyGWorldToGWorld((*theImage)->gworld, (*theParams)->dummy, &(*theImage)->gworld->portRect, &(*theImage)->gworld->portRect, srcCopy, nil); // or from the image directly else theErr = (*theImage)->format->draw((*theImage)->data, theParams); // clean up our drawing, checking for missed aborts if (theErr == noErr) theErr = PostflightDrawing(theParams); else PostflightDrawing(theParams); // if we were aborted, tell the printer so, and close the inner prog. CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressClose, 0L, (*theParams)->progress.prog.progressRefCon); KeepSpinning(); } PopPort(); DisposeHandle((Handle)theParams); } gThePrefs.backgroundTime = oldBackgroundTime; return theErr; } extern OSErr DoSlideShow(void) { NestedProgress theProg = { { nil, 0 }, 0, 0L, 0L, false }; ICMProgressProcRecordPtr progPtr = (ICMProgressProcRecordPtr)&theProg; OSErr theErr = noErr; FSSpec theSpec; if (!(*gSlideOptions)->fromMemory) { theProg.prog.progressProc = gGenericProgress; theProg.prog.progressRefCon = (long)&theProg; UpdateParamText(gString[strScanningDirectory], gNullString, gNullString, gNullString); CallICMProgressProc(theProg.prog.progressProc, codecProgressOpen, kIndefProgress, theProg.prog.progressRefCon); theErr = GetSlideSpec(&theSpec); if (theErr == noErr) if (!WasDesktop(&theSpec, (*gSlideOptions)->recursive, progPtr, &theErr)) theErr = AddSlideDir(&theSpec, (*gSlideOptions)->recursive, progPtr, nil); CallICMProgressProc(theProg.prog.progressProc, codecProgressClose, kIndefProgress, theProg.prog.progressRefCon); } if (theErr == noErr) InitSlideShow(); else { CleanUpSlideShow(); if (theErr == noErr) MinorError(errNoMemory); } return theErr; } static Boolean WasDesktop(FSSpec *spec, Boolean recursive, ICMProgressProcRecordPtr theProg, OSErr *theErr) { HParamBlockRec params; FSSpec theSpec; OSErr err; err = GetDeskFolderSpec(&theSpec, spec->vRefNum); if (err != noErr || !SameFile(&theSpec, spec)) return false; params.volumeParam.ioVolIndex = 1; params.volumeParam.ioCompletion = nil; params.volumeParam.ioNamePtr = theSpec.name; while (PBHGetVInfo(¶ms, false) == noErr && *theErr == noErr) { if (recursive) err = FSMakeFSSpec(params.ioParam.ioVRefNum, 2, "\p", &theSpec); else err = GetDeskFolderSpec(&theSpec, params.volumeParam.ioVRefNum); if (err == noErr) err = AddSlideDir(&theSpec, recursive, theProg, nil); if (err == memFullErr || err == codecAbortErr) *theErr = err; params.volumeParam.ioVolIndex++; } } \ No newline at end of file diff --git a/Source/C/JPEGViewGlobals.c b/Source/C/JPEGViewGlobals.c new file mode 100644 index 0000000..5c4633d --- /dev/null +++ b/Source/C/JPEGViewGlobals.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif AEIdleUPP gAEIdleProc; ICMProgressUPP gGenericProgress, gSlideProgress, gDrawProgress; UserItemUPP gOutlineOK, gPopUpMenuBox, gLineItem; ModalFilterUPP gGenericFilter; ModalFilterYDUPP gOpenSaveModalFilter; /* * Global flags * */ Boolean gInAppleEvent = false, // true if we're operating from within an AppleEvent gInBackground = false, // true if we're running in the background gDone = false, // true to break out of the main event loop & exit JPEGView gMenuVisible = true, // true if the menubar is visible to the user gMenuEnabled = true, // true if the menus are currently enabled gCommentsOpen = false, // true if the user has opened the comments window gHidden = false, // true if we've hidden our windows gGetAbout = false, // true if we're to open an about box gScreenSaver = false, // true if we're running the slide show as a screen saver gSlideFolderValid = false,// true if the slide show folder is valid gFoundOSL = true, // true if we have the Object Support Library gDragMgrPresent = false,// true if the Drag Manager is available gHelpFound = false; // true if the help file was found /* * Default preferences * */ PrefsData gThePrefs = { kPrefsVersion, // Version number sizeof(PrefsData), // Prefs size osDeepest, // Open on deepest screen by default true, // Choose color screens over B&W ofNever, // Never open in full screen false, // Don't expand small images false, // Allow multiple images simultaneously iqVHigh, // Very high quality by default true, // Update background images aqOnly, // Quantize only if there isn't a CLUT true, // Dither quantized images true, // Use image palette by default true, // Restore colors by default ubOptional, // Use bitmaps only if enough memory false, // Not at original size false, // Use bitmaps for uncompressed PICTs as well true, // Automatically fix files types false, // But don't change creators sqOnly, // Only save CLUT if there isn't one already false, // Don't save as PICT by default true, // Save previews by default true, // Compress JFIF previews by default true, // Make custom icons by default isSquareDog, // Square icon style swOpen, // Start with Open dialog true, // No automatic comments window bgReasonable, // Give a reasonable amount of time to BG apps #if defined(powerc) || defined(__powerc) false, // Use IJG code for JPEG decompression #else true, // Use QuickTime for JPEG decompression by default #endif //---------------------------------------- 1, // Initial help section 1, // Initial prefs section true, // Stats initially zoomed 99, // Initial countdown for nags //---------------------------------------- false, // Stats initially not visible false, // Same for comments false, // Same for colors { 0, 0, 0, 0 }, // Set window bounds to 0 to default to { 0, 0, 0, 0 }, // a reasonable position { 0, 0, 0, 0 }, // { 0, 0, 0, 0 }, // { 0, 0, 0, 0 }, // { 0, 0, 0, 0 }, // { 0, 0, 0, 0 }, // { 0, 0, 0, 0 } // }; SlideOptions gDefaultSlideOptions = { false, // Not user-controlled 30, // 30-second slide show delay true, // Shuffle up the slides true, // Repeat indefinitely true, // Don't report minor errors true, // Hide the windoids false, // Don't hide the controls false, // Don't show comments false, // Disk-based slide show false, // Don't scan recursively false, // Don't import other files true, // Show filenames true // Render offscreen first }; SlideOptionsHandle gSlideOptions; /* * Image format routines * */ ImageFormat gPICTFormat = { kPICTType, 0, kPICTType, kStandardQTPreview, kCanSaveQuantization, kCanSaveBanded, kIDIsPositive, "\p", (idImagePtr)idPICT, (LoadImagePtr)LoadPICT, (OpenImagePtr)OpenPICT, (DrawImagePtr)DrawPICT, (FixImagePtr)FixPICT, (SaveImagePtr)SavePICT, (CloneImagePtr)nil, (CloseImagePtr)nil }, gJFIFFormat = { kJPEGType, kJFIFType, kJPEGType, kCustomPreview, kCanSaveQuantization, kCantSaveBanded, kIDIsPositive, "\p", (idImagePtr)idJPEG, (LoadImagePtr)nil, (OpenImagePtr)OpenJPEG, (DrawImagePtr)DrawJPEG, (FixImagePtr)FixJPEG, (SaveImagePtr)SaveJPEG, (CloneImagePtr)nil, (CloseImagePtr)nil }, gGIFFormat = { kGIFType, 0, kGIFType, kStandardQTPreview, kCantSaveQuantization, kCantSaveBanded, kIDIsPositive, "\p", (idImagePtr)idGIF, (LoadImagePtr)nil, (OpenImagePtr)OpenGIF, (DrawImagePtr)DrawGIF, (FixImagePtr)nil, (SaveImagePtr)nil, (CloneImagePtr)nil, (CloseImagePtr)nil }, gTIFFFormat = { kTIFFType, 0, kTIFFType, kStandardQTPreview, kCantSaveQuantization, kCantSaveBanded, kIDIsPositive, "\p", (idImagePtr)idTIFF, (LoadImagePtr)nil, (OpenImagePtr)OpenTIFF, (DrawImagePtr)DrawTIFF, (FixImagePtr)nil, (SaveImagePtr)nil, (CloneImagePtr)CloneTIFF, (CloseImagePtr)CloseTIFF }, gBMPFormat = { kBMPType, 0, kBMPType, kStandardQTPreview, kCantSaveQuantization, kCantSaveBanded, kIDIsPositive, "\p", (idImagePtr)idBMP, (LoadImagePtr)nil, (OpenImagePtr)OpenBMP, (DrawImagePtr)DrawBMP, (FixImagePtr)nil, (SaveImagePtr)nil, (CloneImagePtr)CloneBMP, (CloseImagePtr)CloseBMP }, gSCRNFormat = { kSCRNType, 0, kSCRNType, kStandardQTPreview, kCanSaveQuantization, kCanSaveBanded, kIDIsPossible, "\p", (idImagePtr)idSCRN, (LoadImagePtr)LoadSCRN, (OpenImagePtr)OpenSCRN, (DrawImagePtr)DrawSCRN, (FixImagePtr)nil, (SaveImagePtr)SaveSCRN, (CloneImagePtr)nil, (CloseImagePtr)nil }, gPNTGFormat = { kPNTGType, 0, kPNTGType, kStandardQTPreview, kCantSaveQuantization, kCantSaveBanded, kIDIsPossible, "\p", (idImagePtr)idPNTG, (LoadImagePtr)nil, (OpenImagePtr)OpenPNTG, (DrawImagePtr)DrawPNTG, (FixImagePtr)nil, (SaveImagePtr)nil, (CloneImagePtr)nil, (CloseImagePtr)nil }, gPICTRFormat = { 0, 0, kSCRNType, kStandardQTPreview, kCanSaveQuantization, kCanSaveBanded, kIDIsPossible, "\p", (idImagePtr)nil, (LoadImagePtr)nil, (OpenImagePtr)nil, (DrawImagePtr)nil, (FixImagePtr)FixSCRN, (SaveImagePtr)SaveSCRN, (CloneImagePtr)nil, (CloseImagePtr)nil }; ImageFormatPtr gFormat[kFileFormats] = { &gPICTFormat, &gJFIFFormat, &gGIFFormat, &gTIFFFormat, &gBMPFormat, &gSCRNFormat, &gPNTGFormat, &gPICTRFormat }; /* * RGB Color Specs * */ RGBColor gBlack = { 0x0000, 0x0000, 0x0000 }, // Black gWhite = { 0xffff, 0xffff, 0xffff }, // White gFGrey = { 0x1111, 0x1111, 0x1111 }; // Windowframe Grey /* * Other globals * */ #if defined(powerc) || defined(__powerc) #ifndef __MWERKS__ QDGlobals qd; #endif #endif NMRec gTheNotification; // Notification Mgr. record THPrint gPrintRecord = nil; // the global print record ImageHandle gDrawing = nil, // handle to image we're currently drawing gImageRoot = nil; // pointer to the root of the linked list of images MonitorHandle gMainMonitor = nil; // pointer to the main monitor; also head of linked list MenuHandle gAppleMenu; // handle to the Apple menu CursHandle gCross, // handle to the cross cursor gHand, // handle to the hand cursor gSize; // handle to the size-box cursor PaletteHandle gColorPalette[9], // handle to color palettes of varying depths (1,2,4,8) gGreyPalette[9]; // handle to greyscale palettes of varying depths (4,8) DialogRecord *gPortPool; // pointer to the pool of WindowPtrs we have GWorldPtr gGenericGWorld, // pointer to the generic GWorld gPreviewGWorld, // pointer to the preview GWorld gIconGWorld; // pointer to the icon GWorld CodecInfo gJPEGInfo; // the codec information record for the JPEG codec PrefsData gOldPrefs; // area for temporarily holding the old preferences data StringPtr gString[kNumStrings], // pointers to all our resource-based strings gNullString = (StringPtr)"\p"; // a null string NestedProgress gDummyProg = { { nil, 0 }, 0, 0L, 0x10000L, false }; // Dummy progress procedure FSSpec gSlideSpec; // file specification of Point gScreenSaverPoint; // initial location of the mouse when slide show started Handle gIconSuite = nil; // handle to the JPEGView application icon suite long gQTVersion = 0, // the version of QuickTime we found gBadWindowID, // ID of the window we were unable to find (for Open events) gMemSlop = 96L * 1024L; // amount of memory to reserve for internal buffer use short gTitleBarHeight, // height of a window's titlebar gMenuHeight, // the original height of the menubar gIntError = 0, // internal error number gPendingButton = -1, // pending slide show button gHelpItem; // item number of our JPEGView Help short *gErrTable = nil; // pointer to table for truncating dithering errors uchar *gScaleTable, // pointer to a table for fast scaling gThousandsSep = ',', // character for thousands separation gDecimal = '.', // character for decimal point gListSep = ','; // character for list separation char gSlideShow = 0; // status of the slide show \ No newline at end of file diff --git a/Source/C/MarchingAnts.c b/Source/C/MarchingAnts.c new file mode 100644 index 0000000..cdca3ee --- /dev/null +++ b/Source/C/MarchingAnts.c @@ -0,0 +1 @@ +//===================================================================================== // MarchingAnts.c -- written by Aaron Giles // Last update: 4/19/94 (version 1.0) //===================================================================================== // A source code library for handling rectangular graphical selections involving the // famous "marching ants". See the header file for a brief description of each // function; see the prelude to each function definition below for a full description // of its operation and expected use. //===================================================================================== // This code has been compiled successfully under MPW C, MPW PPCC, THINK C, and // Metrowerks C/C++, both 68k and PowerPC. This code has been compiled under both the // Universal Headers and the old 7.1 headers; if it works earlier than that I cannot // say for sure. //===================================================================================== // If you find any bugs in this source code, please email me and I will attempt to fix // them. If you have any additions/modifications that you think would be generally // useful, email those to me as well, and I will consider incorporating them into the // next release. My email address is giles@med.cornell.edu. //===================================================================================== // This source code is copyright © 1994, Aaron Giles. Permission to use this code in // your product is freely granted, provided that you credit me appropriately in your // application's About box/credits *and* documentation. If you ship an application // which uses this code, I would also like to request that you provide me with one // complimentary copy of the application. //===================================================================================== //===================================================================================== // Include standard MacOS definitions. //===================================================================================== #include #include #include #include #include #include //===================================================================================== // Include our own external definitions. //===================================================================================== #include "MarchingAnts.h" //===================================================================================== // Prototypes for internal functions local to this module. //===================================================================================== static OSErr DrawAnts(AntsReference theAnts); static OSErr EraseAnts(AntsReference theAnts); static OSErr MarchAnts(AntsReference theAnts); static void SaveToGWorlds(AntsReference theAnts); static void RestoreFromGWorlds(AntsReference theAnts); static void CopyToCurrentPort(GWorldPtr srcGWorld, Rect *srcRect, Rect *dstRect); static void CopyFromCurrentPort(GWorldPtr dstGWorld, Rect *srcRect, Rect *dstRect); //===================================================================================== // Internal global variable declarations. //===================================================================================== static Pattern gAnimatedAntsPatternTop = { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 }; static Pattern gAnimatedAntsPatternBottom = { 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 }; static Pattern gAnimatedAntsPatternLeft = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; static Pattern gAnimatedAntsPatternRight = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; static Pattern gInactiveAntsPattern = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }; //===================================================================================== // AntsReference NewAnts(void) //===================================================================================== // Allocates memory for a new marching ants record. The newly-created ants are by // default active but not visible, and have no selection. Following this call, you // will need to set the ants' port (SetAntsPort()) and the limit rectangle // (SetAntsLimitRect()) before doing anything really useful. This function returns nil // if memory is incredibly tight. //===================================================================================== extern AntsReference NewAnts(void) { AntsReference theAnts = (AntsReference)NewHandleClear(sizeof(AntsRecord)); if (theAnts) (*theAnts)->active = true; // active by default return theAnts; } //===================================================================================== // void DisposeAnts(AntsReference theAnts) //===================================================================================== // Disposes of all memory allocated for drawing the ants specified by theAnts. After // this function is called, the AntsReference is no longer valid. //===================================================================================== extern void DisposeAnts(AntsReference theAnts) { if ((*theAnts)->verticalWorld) DisposeGWorld((*theAnts)->verticalWorld); if ((*theAnts)->horizontalWorld) DisposeGWorld((*theAnts)->horizontalWorld); DisposeHandle((Handle)theAnts); } //===================================================================================== // Boolean AntsHaveSelection(AntsReference theAnts) //===================================================================================== // Returns true if the specified ants have a non-nil selection. Use this function to // determine if there is, in fact, some selected area you should be operating on. //===================================================================================== extern Boolean AntsHaveSelection(AntsReference theAnts) { return (((*theAnts)->bounds.right - (*theAnts)->bounds.left) > antsMinimumX && ((*theAnts)->bounds.bottom - (*theAnts)->bounds.top) > antsMinimumY); } //===================================================================================== // void GetAntsSelection(AntsReference theAnts, Rect *theBounds) //===================================================================================== // Returns, in theBounds, the current selection specified by theAnts. If there is no // selection, this function will return the rectangle { 0, 0, 0, 0 }, so be careful if // you're doing something like calling MapRect() on it. //===================================================================================== extern void GetAntsSelection(AntsReference theAnts, Rect *theBounds) { *theBounds = (*theAnts)->bounds; } //===================================================================================== // void SetAntsSelection(AntsReference theAnts, Rect *newBounds) //===================================================================================== // Changes the current selection specified by theAnts to the rectangle described by // newBounds. If the ants are currently visible, they are hidden and then reshown // after the operation is complete. Attempting to set the selection to anything // smaller than 8 pixels in any direction will create a nil selection, causing any // visible selection to disappear. An easier way of doing this latter operation is to // simply call ResetAntsSelection(), described below. //===================================================================================== extern void SetAntsSelection(AntsReference theAnts, Rect *newBounds) { Boolean wasDrawn = (*theAnts)->drawn; if (wasDrawn) HideAnts(theAnts); if (newBounds->left != (*theAnts)->bounds.left || newBounds->right != (*theAnts)->bounds.right || newBounds->top != (*theAnts)->bounds.top || newBounds->bottom != (*theAnts)->bounds.bottom) { if ((*theAnts)->horizontalWorld) DisposeGWorld((*theAnts)->horizontalWorld), (*theAnts)->horizontalWorld = nil; if ((*theAnts)->verticalWorld) DisposeGWorld((*theAnts)->verticalWorld), (*theAnts)->verticalWorld = nil; } if ((newBounds->right - newBounds->left) > antsMinimumX && (newBounds->bottom - newBounds->top) > antsMinimumY) { (*theAnts)->bounds = *newBounds; } else (*theAnts)->bounds.top = (*theAnts)->bounds.bottom = (*theAnts)->bounds.left = (*theAnts)->bounds.right = 0; if (wasDrawn) ShowAnts(theAnts); } //===================================================================================== // void ResetAntsSelection(AntsReference theAnts) //===================================================================================== // Clears the current selection specified by theAnts to nil. If the ants are currently // visible, the visible selection will disappear. //===================================================================================== extern void ResetAntsSelection(AntsReference theAnts) { static Rect gNullRect = { 0, 0, 0, 0 }; HideAnts(theAnts); SetAntsSelection(theAnts, &gNullRect); } //===================================================================================== // void GetAntsLimitRect(AntsReference theAnts, Rect *limitRect) //===================================================================================== // Returns in limitRect the current limit rectangle specified by theAnts. See also // the function SetAntsLimitRect() for a full description of what the limit rectangle // does. //===================================================================================== extern void GetAntsLimitRect(AntsReference theAnts, Rect *limitRect) { *limitRect = (*theAnts)->limitRect; } //===================================================================================== // void SetAntsLimitRect(AntsReference theAnts, Rect *newLimit) //===================================================================================== // Sets the limit rectangle for theAnts to the rectangle newLimit. The limit rectangle // is used in two places, and it is important that you update this value whenever your // window changes size. The first and most common place the limit rectangle is used is // when drawing the ants; in this case, the limit rectangle is used as the clipping // rectangle for drawing. The limit rectangle is also used when tracking the mouse // during a selection, to specify the outermost boundaries of the area the user may // select. //===================================================================================== extern void SetAntsLimitRect(AntsReference theAnts, Rect *newLimit) { (*theAnts)->limitRect = *newLimit; } //===================================================================================== // GrafPtr GetAntsPort(AntsReference theAnts) //===================================================================================== // Returns the port the ants are currently drawn into. Use the SetAntsPort() function, // below, to change the associated GrafPort. //===================================================================================== extern GrafPtr GetAntsPort(AntsReference theAnts) { return (*theAnts)->port; } //===================================================================================== // void SetAntsPort(AntsReference theAnts, GrafPtr thePort) //===================================================================================== // Use this function to set the ants' destination port. The destination port // determines where the ants will be drawn and tracked. //===================================================================================== extern void SetAntsPort(AntsReference theAnts, GrafPtr thePort) { (*theAnts)->port = thePort; } //===================================================================================== // Boolean AreAntsVisible(AntsReference theAnts) //===================================================================================== // Returns true if the ants are currently visible. Note that this merely reflects the // state of the internal visible flag, which can be set by the HideAnts() and // ShowAnts() functions. //===================================================================================== extern Boolean AreAntsVisible(AntsReference theAnts) { return (*theAnts)->visible; } //===================================================================================== // void TrackAntsSelection(AntsReference theAnts, Point localStart) //===================================================================================== // Call this function to track the mouse as a new selection is made. The point // localStart is the location of mouse down event, in global coordinates. Once this // function returns, you can use the AntsHaveSelection() function to determine if a // selection was, in fact, made. //===================================================================================== extern void TrackAntsSelection(AntsReference theAnts, Point localStart) { static Pattern gTrackSelectionPattern = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }; Rect newBounds, limitRect = (*theAnts)->limitRect; Point lastPoint, newPoint; RgnHandle saveClip; PenState oldState; GrafPtr oldPort; long pinned; GetPort(&oldPort); SetPort((*theAnts)->port); if (saveClip = NewRgn()) { GetClip(saveClip); ClipRect(&limitRect); GetPenState(&oldState); PenNormal(); PenMode(srcXor); PenPat(&gTrackSelectionPattern); lastPoint = localStart; newBounds.left = newBounds.right = localStart.h; newBounds.top = newBounds.bottom = localStart.v; FrameRect(&newBounds); while (StillDown()) { GetMouse(&newPoint); if (newPoint.h == lastPoint.h && newPoint.v == lastPoint.v) continue; pinned = PinRect(&limitRect, newPoint); newPoint = *(Point *)&pinned; FrameRect(&newBounds); if (newPoint.h > localStart.h) { newBounds.left = localStart.h; newBounds.right = newPoint.h + 1; } else { newBounds.left = newPoint.h; newBounds.right = localStart.h + 1; } if (newPoint.v > localStart.v) { newBounds.top = localStart.v; newBounds.bottom = newPoint.v + 1; } else { newBounds.top = newPoint.v; newBounds.bottom = localStart.v + 1; } FrameRect(&newBounds); lastPoint = newPoint; } FrameRect(&newBounds); SetAntsSelection(theAnts, &newBounds); SetPenState(&oldState); SetClip(saveClip); DisposeRgn(saveClip); } SetPort(oldPort); } //===================================================================================== // void ShowAnts(AntsReference theAnts) //===================================================================================== // This function forces the ants to become visible if they weren't already. At this // time we also save what is currently behind the selection rectangle in GWorlds so // that we can do a clean restore. Note that this is the *only* time we save the area // behind the ants. However, this is usually ok, since we need to call HideAnts() // before doing any drawing anyhow, and then ShowAnts() again after the drawing is // complete. //===================================================================================== extern void ShowAnts(AntsReference theAnts) { (*theAnts)->visible = true; if (!(*theAnts)->drawn) { SaveToGWorlds(theAnts); DrawAnts(theAnts); } } //===================================================================================== // void HideAnts(AntsReference theAnts) //===================================================================================== // This function hides the ants and restores any background behind them. This function // should get called before any drawing occurs, so as not to overwrite the current // ants. //===================================================================================== extern void HideAnts(AntsReference theAnts) { if ((*theAnts)->drawn) EraseAnts(theAnts); (*theAnts)->visible = false; } //===================================================================================== // void AnimateAnts(AntsReference theAnts) //===================================================================================== // This function rotates the ants forward one notch and redraws them. Call this // function in your null event handler, whenever the time is appropriate. //===================================================================================== extern void AnimateAnts(AntsReference theAnts) { if (!(*theAnts)->verticalWorld || !(*theAnts)->horizontalWorld) EraseAnts(theAnts); MarchAnts(theAnts); DrawAnts(theAnts); } //===================================================================================== // void ActivateAnts(AntsReference theAnts) //===================================================================================== // Call this function to activate the specified ants selection (i.e., when the window // the ants are in receives an activate event). This means that the ants will be // displayed as an animated dashed rectangle that rotates whenever AnimateAnts() is // called. //===================================================================================== extern void ActivateAnts(AntsReference theAnts) { if (!(*theAnts)->verticalWorld || !(*theAnts)->horizontalWorld) EraseAnts(theAnts); (*theAnts)->active = true; DrawAnts(theAnts); } //===================================================================================== // void DeactivateAnts(AntsReference theAnts) //===================================================================================== // Call this function to deactivate the specified ants selection (i.e., when the window // the ants are in receives an deactivate event). This means that the ants will be // displayed as a steady dotted rectangle which does nothing when AnimateAnts() is // called. //===================================================================================== extern void DeactivateAnts(AntsReference theAnts) { if (!(*theAnts)->verticalWorld || !(*theAnts)->horizontalWorld) EraseAnts(theAnts); (*theAnts)->active = false; DrawAnts(theAnts); } /************************************************************************************** *************************************************************************************** ********** ********** ********** ********** ********** E N D O F P U B L I C I N T E R F A C E S ********** ********** ********** ********** ********** *************************************************************************************** **************************************************************************************/ //===================================================================================== // OSErr DrawAnts(AntsReference theAnts) //===================================================================================== // INTERNAL FUNCTION. Draws the ants if they are supposed to be visible. If there was // enough memory for the offscreen GWorlds, we draw them using srcCopy mode to make // them nice and visible. If there was not enough memory for the GWorlds, we use // srcXor mode instead so that things still work, if not as prettily. //===================================================================================== static OSErr DrawAnts(AntsReference theAnts) { OSErr theErr = noErr; RgnHandle saveClip; PenState oldState; GrafPtr oldPort; Rect theRect; if (!(*theAnts)->visible) return noErr; theRect = (*theAnts)->bounds; if ((theRect.bottom - theRect.top) == 0 || (theRect.right - theRect.left) == 0) return noErr; GetPort(&oldPort); SetPort((*theAnts)->port); if (saveClip = NewRgn()) { GetClip(saveClip); theRect = (*theAnts)->limitRect; ClipRect(&theRect); GetPenState(&oldState); PenNormal(); if (!(*theAnts)->horizontalWorld || !(*theAnts)->verticalWorld) PenMode(srcXor); else PenMode(srcCopy); MoveTo((*theAnts)->bounds.left, (*theAnts)->bounds.top); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternTop); else PenPat(&gInactiveAntsPattern); LineTo((*theAnts)->bounds.right - 1, (*theAnts)->bounds.top); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternRight); LineTo((*theAnts)->bounds.right - 1, (*theAnts)->bounds.bottom - 1); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternBottom); LineTo((*theAnts)->bounds.left, (*theAnts)->bounds.bottom - 1); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternLeft); LineTo((*theAnts)->bounds.left, (*theAnts)->bounds.top); SetPenState(&oldState); (*theAnts)->drawn = true; SetClip(saveClip); DisposeRgn(saveClip); } else theErr = memFullErr; SetPort(oldPort); return theErr; } //===================================================================================== // OSErr EraseAnts(AntsReference theAnts) //===================================================================================== // INTERNAL FUNCTION. Erases the ants if they are supposed to be visible. If there // was enough memory for the offscreen GWorlds, we copy their contents back into the // window. If there was not enough memory for the GWorlds, we just redraw the ants // using srcXor mode which erases them. //===================================================================================== static OSErr EraseAnts(AntsReference theAnts) { OSErr theErr = noErr; RgnHandle saveClip; PenState oldState; GrafPtr oldPort; Rect theRect; theRect = (*theAnts)->bounds; if ((theRect.bottom - theRect.top) == 0 || (theRect.right - theRect.left) == 0) return noErr; GetPort(&oldPort); SetPort((*theAnts)->port); if (saveClip = NewRgn()) { GetClip(saveClip); theRect = (*theAnts)->limitRect; ClipRect(&theRect); GetPenState(&oldState); PenNormal(); if (!(*theAnts)->horizontalWorld || !(*theAnts)->verticalWorld) { PenMode(srcXor); MoveTo((*theAnts)->bounds.left, (*theAnts)->bounds.top); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternTop); else PenPat(&gInactiveAntsPattern); LineTo((*theAnts)->bounds.right - 1, (*theAnts)->bounds.top); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternRight); LineTo((*theAnts)->bounds.right - 1, (*theAnts)->bounds.bottom - 1); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternBottom); LineTo((*theAnts)->bounds.left, (*theAnts)->bounds.bottom - 1); if ((*theAnts)->active) PenPat(&gAnimatedAntsPatternLeft); LineTo((*theAnts)->bounds.left, (*theAnts)->bounds.top); SetPenState(&oldState); } else RestoreFromGWorlds(theAnts); (*theAnts)->drawn = false; SetClip(saveClip); DisposeRgn(saveClip); } else theErr = memFullErr; SetPort(oldPort); return theErr; } //===================================================================================== // OSErr MarchAnts(AntsReference theAnts) //===================================================================================== // INTERNAL FUNCTION. Rotates the QuickDraw patterns used to draw the ants. //===================================================================================== static OSErr MarchAnts(AntsReference theAnts) { #if applec #pragma unused(theAnts) #endif char temp; int i; #ifdef dangerousPattern temp = ((gAnimatedAntsPatternTop[0] & 1) ? 0x80 : 0) + (gAnimatedAntsPatternTop[0] >> 1); for (i = 0; i < 8; i++) gAnimatedAntsPatternTop[i] = temp; temp = ((gAnimatedAntsPatternBottom[0] & 0x80) ? 1 : 0) + (gAnimatedAntsPatternBottom[0] << 1); for (i = 0; i < 8; i++) gAnimatedAntsPatternBottom[i] = temp; temp = gAnimatedAntsPatternRight[7]; for (i = 7; i > 0; i--) gAnimatedAntsPatternRight[i] = gAnimatedAntsPatternRight[i - 1]; gAnimatedAntsPatternRight[0] = temp; temp = gAnimatedAntsPatternLeft[0]; for (i = 0; i < 7; i++) gAnimatedAntsPatternLeft[i] = gAnimatedAntsPatternLeft[i + 1]; gAnimatedAntsPatternLeft[7] = temp; #else temp = ((gAnimatedAntsPatternTop.pat[0] & 1) ? 0x80 : 0) + (gAnimatedAntsPatternTop.pat[0] >> 1); for (i = 0; i < 8; i++) gAnimatedAntsPatternTop.pat[i] = temp; temp = ((gAnimatedAntsPatternBottom.pat[0] & 0x80) ? 1 : 0) + (gAnimatedAntsPatternBottom.pat[0] << 1); for (i = 0; i < 8; i++) gAnimatedAntsPatternBottom.pat[i] = temp; temp = gAnimatedAntsPatternRight.pat[7]; for (i = 7; i > 0; i--) gAnimatedAntsPatternRight.pat[i] = gAnimatedAntsPatternRight.pat[i - 1]; gAnimatedAntsPatternRight.pat[0] = temp; temp = gAnimatedAntsPatternLeft.pat[0]; for (i = 0; i < 7; i++) gAnimatedAntsPatternLeft.pat[i] = gAnimatedAntsPatternLeft.pat[i + 1]; gAnimatedAntsPatternLeft.pat[7] = temp; #endif return noErr; } //===================================================================================== // void SaveToGWorlds(AntsReference theAnts) //===================================================================================== // INTERNAL FUNCTION. Attempts to create offscreen GWorlds for saving the area // behind the ants. If successful, we go ahead and do CopyBits from the screen(s) to // the GWorlds; otherwise, we leave the GWorldPtrs set to nil to indicate that we // should draw using srcXor instead. //===================================================================================== static void SaveToGWorlds(AntsReference theAnts) { Rect srcRect, dstRect; GWorldPtr theGWorld; OSErr theErr; Rect theRect; if (!(*theAnts)->horizontalWorld) { theRect = (*theAnts)->bounds; theRect.bottom = theRect.top + 2; OffsetRect(&theRect, -theRect.left, -theRect.top); theErr = NewGWorld(&theGWorld, 32, &theRect, nil, nil, 0); if (theErr == noErr && theGWorld) (*theAnts)->horizontalWorld = theGWorld; else return; } if (!(*theAnts)->verticalWorld) { theRect = (*theAnts)->bounds; theRect.right = theRect.left + 2; OffsetRect(&theRect, -theRect.left, -theRect.top); theErr = NewGWorld(&theGWorld, 32, &theRect, nil, nil, 0); if (theErr == noErr && theGWorld) (*theAnts)->verticalWorld = theGWorld; else return; } srcRect = (*theAnts)->bounds; srcRect.bottom = srcRect.top + 1; dstRect = srcRect; OffsetRect(&dstRect, -dstRect.left, -dstRect.top); CopyFromCurrentPort((*theAnts)->horizontalWorld, &srcRect, &dstRect); srcRect.bottom = (*theAnts)->bounds.bottom; srcRect.top = srcRect.bottom - 1; dstRect.top++; dstRect.bottom++; CopyFromCurrentPort((*theAnts)->horizontalWorld, &srcRect, &dstRect); srcRect = (*theAnts)->bounds; srcRect.right = srcRect.left + 1; dstRect = srcRect; OffsetRect(&dstRect, -dstRect.left, -dstRect.top); CopyFromCurrentPort((*theAnts)->verticalWorld, &srcRect, &dstRect); srcRect.right = (*theAnts)->bounds.right; srcRect.left = srcRect.right - 1; dstRect.left++; dstRect.right++; CopyFromCurrentPort((*theAnts)->verticalWorld, &srcRect, &dstRect); } //===================================================================================== // void RestoreFromGWorlds(AntsReference theAnts) //===================================================================================== // INTERNAL FUNCTION. Restores the original pixels from the GWorlds saved in the // specified ants record. //===================================================================================== static void RestoreFromGWorlds(AntsReference theAnts) { static RGBColor gBlack = { 0x0000, 0x0000, 0x0000 }, gWhite = { 0xffff, 0xffff, 0xffff }; Rect srcRect, dstRect; RGBForeColor(&gBlack); RGBBackColor(&gWhite); dstRect = (*theAnts)->bounds; dstRect.bottom = dstRect.top + 1; srcRect = dstRect; OffsetRect(&srcRect, -srcRect.left, -srcRect.top); CopyToCurrentPort((*theAnts)->horizontalWorld, &srcRect, &dstRect); dstRect.bottom = (*theAnts)->bounds.bottom; dstRect.top = dstRect.bottom - 1; srcRect.top++; srcRect.bottom++; CopyToCurrentPort((*theAnts)->horizontalWorld, &srcRect, &dstRect); dstRect = (*theAnts)->bounds; dstRect.right = dstRect.left + 1; srcRect = dstRect; OffsetRect(&srcRect, -srcRect.left, -srcRect.top); CopyToCurrentPort((*theAnts)->verticalWorld, &srcRect, &dstRect); dstRect.right = (*theAnts)->bounds.right; dstRect.left = dstRect.right - 1; srcRect.left++; srcRect.right++; CopyToCurrentPort((*theAnts)->verticalWorld, &srcRect, &dstRect); } //===================================================================================== // void CopyToCurrentPort(GWorldPtr srcGWorld, Rect *srcRect, Rect *dstRect) //===================================================================================== // INTERNAL FUNCTION. Performs a CopyBits operation from the specified offscreen // GWorld to the current onscreen port, mapping from srcRect to dstRect. This makes // our life easier by taking care of foreground/background colors, destination ports, // and locked offscreen PixMaps. //===================================================================================== static void CopyToCurrentPort(GWorldPtr srcGWorld, Rect *srcRect, Rect *dstRect) { static RGBColor gBlack = { 0x0000, 0x0000, 0x0000 }, gWhite = { 0xffff, 0xffff, 0xffff }; PixMapHandle srcPixMap, dstPixMap; char pixelsState; GrafPtr thePort; RGBForeColor(&gBlack); RGBBackColor(&gWhite); GetPort(&thePort); srcPixMap = GetGWorldPixMap(srcGWorld); dstPixMap = GetGWorldPixMap((CGrafPtr)thePort); pixelsState = GetPixelsState(srcPixMap); LockPixels(srcPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, srcRect, dstRect, srcCopy, nil); SetPixelsState(srcPixMap, pixelsState); } //===================================================================================== // void CopyFromCurrentPort(GWorldPtr srcGWorld, Rect *srcRect, Rect *dstRect) //===================================================================================== // INTERNAL FUNCTION. Performs a CopyBits operation from the current onscreen port // to the specified offscreen GWorld, mapping from srcRect to dstRect. This makes our // life easier by taking care of foreground/background colors, destination ports, and // locked offscreen PixMaps. //===================================================================================== static void CopyFromCurrentPort(GWorldPtr dstGWorld, Rect *srcRect, Rect *dstRect) { PixMapHandle srcPixMap, dstPixMap; RgnHandle maskRgn; char pixelsState; GrafPtr thePort; if (maskRgn = NewRgn()) { GetPort(&thePort); SetGWorld(dstGWorld, nil); RectRgn(maskRgn, srcRect); SectRgn(maskRgn, thePort->visRgn, maskRgn); OffsetRgn(maskRgn, dstRect->left - srcRect->left, dstRect->top - srcRect->top); srcPixMap = GetGWorldPixMap((CGrafPtr)thePort); dstPixMap = GetGWorldPixMap(dstGWorld); pixelsState = GetPixelsState(dstPixMap); LockPixels(dstPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, srcRect, dstRect, srcCopy, maskRgn); SetPixelsState(dstPixMap, pixelsState); SetGWorld((CGrafPtr)thePort, nil); DisposeRgn(maskRgn); } } \ No newline at end of file diff --git a/Source/C/MemoryUtils.c b/Source/C/MemoryUtils.c new file mode 100644 index 0000000..d749f52 --- /dev/null +++ b/Source/C/MemoryUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif #include /* * AllocatePort() * * Purpose: Allocates a port (actually a dialog record) from our global pool * Inputs: none * Returns: a pointer to the memory location * */ CGrafPtr AllocatePort(void) { int i; for (i = 0; i < kMaxPorts; i++) if (!gPortPool[i].window.port.portBits.baseAddr) { gPortPool[i].window.port.portBits.baseAddr = (Ptr)0xffffffff; return (CGrafPtr)&gPortPool[i]; } return nil; } /* * DecallocatePort(thePort) * * Purpose: Deallocates a port from our global pool * Inputs: thePort = the port to deallocate * Returns: nothing * */ void DeallocatePort(CGrafPtr thePort) { Ptr theStart = StripAddress(gPortPool); Ptr theEnd = theStart + kMaxPorts * sizeof(DialogRecord); Ptr theAdr = StripAddress(thePort); short i; if ((theAdr >= theStart) && (theAdr < theEnd)) for (i = 0; i < sizeof(DialogRecord); i++) *theAdr++ = 0; } /* * CheckedNewHandle(theSize, canForce) * * Purpose: Allocates a handle, either in the application heap or in the system heap * Inputs: theSize = the size of the handle to allocate * canForce = true if we're allowed to delete GWorlds to force memory * Returns: a new handle, or nil if not enough memory * */ Handle CheckedNewHandle(Size theSize, Boolean canForce) { OSErr theErr = noErr; Handle theHandle; if (!IsMemAvailable(theSize) || !(theHandle = NewHandle(theSize))) { theHandle = TempNewHandle(theSize, &theErr); if (theErr != noErr && canForce) { if (!MakeMemAvailable(theSize) || !(theHandle = NewHandle(theSize))) return nil; } } return (theErr == noErr) ? theHandle : nil; } /* * AnyNewHandle(theSize) * * Purpose: Allocates a handle, either in the application heap or in the system heap * Inputs: theSize = the size of the handle to allocate * Returns: a new handle, or nil if not enough memory * */ Handle AnyNewHandle(Size theSize) { OSErr theErr = noErr; Handle theHandle; if (!(theHandle = NewHandle(theSize))) theHandle = TempNewHandle(theSize, &theErr); return (theErr == noErr) ? theHandle : nil; } /* * ClearMem(thePtr, theSize) * * Purpose: Zeroes out a block of memory * Inputs: thePtr = pointer to the memory * theSize = the size of the block to clear * Returns: nothing * */ void ClearMem(Ptr thePtr, register Size theSize) { register union { uchar *cPtr; ushort *sPtr; ulong *lPtr; } p; p.cPtr = (uchar *)thePtr; if (theSize && ((long)p.cPtr & 1)) *p.cPtr++ = 0, theSize--; if (theSize && ((long)p.sPtr & 2)) *p.sPtr++ = 0, theSize -= 2; while (theSize >= 4) *p.lPtr++ = 0, theSize -= 4; if (theSize >= 2) *p.sPtr++ = 0, theSize -= 2; if (theSize) *p.cPtr++ = 0; // memset(thePtr, 0, theSize); } /* * GWorldSize(theGWorld) * * Purpose: Returns the real size of the given GWorld * Inputs: theGWorld = a pointer to the GWorld * Returns: the size, in bytes * */ long GWorldSize(GWorldPtr theGWorld) { long theSize = sizeof(CGrafPort) + sizeof(GDevice) + 4096; PixMapHandle thePixMap; if (!theGWorld) return 0; thePixMap = GetGWorldPixMap(theGWorld); if (thePixMap) { if ((*thePixMap)->pmTable) { theSize += (sizeof(ColorTable) + sizeof(ColorSpec) * ((*(*thePixMap)->pmTable)->ctSize + 1)); theSize += (1L << (*gMainMonitor)->oldres) * (1L << (*gMainMonitor)->oldres) * (1L << (*gMainMonitor)->oldres); } theSize += (long)((*thePixMap)->rowBytes & 0x3fff) * (long)Height(&(*thePixMap)->bounds); } return theSize; } /* * EstGWorldSize(bounds, depth) * * Purpose: Returns an estimate of the GWorld size for a given rectangle and depth * Inputs: bounds = the bounding rectange of the proposed GWorld * depth = the proposed depth * Returns: the size, in bytes * */ long EstGWorldSize(Rect *bounds, short depth) { long theSize = sizeof(CGrafPort) + sizeof(GDevice) + 16384L; if (depth <= 8) { theSize += sizeof(ColorTable) + sizeof(ColorSpec) * (1 << depth); theSize += (1 << (*gMainMonitor)->oldres) * (1 << (*gMainMonitor)->oldres) * (1 << (*gMainMonitor)->oldres); } theSize += (((long)Width(bounds) * (long)depth) / 8L + 4L) * (long)Height(bounds); return theSize; } /* * IsMemAvailable(request) * * Purpose: Determines in a block of memory of the given size is available * Inputs: request = the requested memory size * Returns: true if there's room; false otherwise * */ Boolean IsMemAvailable(long request) { long total, contig; if (MaxBlock() > (request + gMemSlop)) return true; PurgeSpace(&total, &contig); return (request < contig) && ((request + gMemSlop) < total); } /* * MakeMemAvailable(request) * * Purpose: Determines in a block of memory of the given size is available; * if not, we try killing off some GWorlds to do it * Inputs: request = the requested memory size * Returns: true if there's room; false otherwise * */ Boolean MakeMemAvailable(long request) { Boolean answer; while (!(answer = IsMemAvailable(request)) && GetMem()); return answer; } /* * GetMem() * * Purpose: Kills off the GWorld of the most-hidden window * Inputs: none * Returns: true if we found something to kill; false if we're out of options * */ long GetMem(void) { WindowPtr theWindow, bestWindow = nil; ImageHandle theImage, bestImage; long theSize; if (gThePrefs.useBitmaps == ubAlways) return 0; for (theWindow = FWFrontWindow(); theWindow; theWindow = NextWindow(theWindow)) if ((theImage = FindImage(theWindow)) && (*theImage)->gworld) { bestWindow = theWindow; bestImage = theImage; } if (bestWindow == nil) return 0; theSize = GWorldSize((*bestImage)->gworld); KillGWorld(bestImage); return theSize; } /* * GrowZone(cbNeeded) * * Purpose: Called in emergencies; kills off unnecessary GWorlds * Inputs: cbNeeded = the number of bytes we need * Returns: the number of bytes we freed * */ pascal long GrowZone(Size cbNeeded) { #if applec #pragma unused(cbNeeded) #endif return 0; /* long theA5 = SetCurrentA5(), val; short tmpVal = gThePrefs.useBitmaps; if (tmpVal == ubAlways) gThePrefs.useBitmaps = ubOptional; val = GetMem(); gThePrefs.useBitmaps = tmpVal; theA5 = SetA5(theA5); return val;*/ } \ No newline at end of file diff --git a/Source/C/MercutioAPI.c b/Source/C/MercutioAPI.c new file mode 100644 index 0000000..77d3a2f --- /dev/null +++ b/Source/C/MercutioAPI.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //#include //#include // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // xxx // xxx Developer's Programming Interface for Mercutio Menu Definition Function // xxx ©1992 Ramon M. Felciano, All Rights Reserved // xxx // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // // Ported to THINK C, 7 Mar 1993 by Aaron Giles // Updated constants for Mercutio 1.2, 19 May 1993 by Aaron Giles // static pascal Boolean IsCustomMenu(MenuHandle menu); // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // x // x PowerMenuKey is a replacement for the standard toolbox call MenuKey for use with the // x Mercutio. Given the keypress message and modifiers parameters from a standard event, it // x checks to see if the keypress is a key-equivalent for a particular menuitem. If you are currently // x using custom menus (i.e. menus using Mercutio), pass the handle to one of these menus in // x hMenu. If you are not using custom menus, pass in NIL or another menu, and PowerMenuKey will use the // x standard MenuKey function to interpret the keypress. // x // x As with MenuKey, PowerMenuKey returns the menu ID in high word of the result, and the menu // x item in the low word. // x // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx #define customDefProcSig 'CUST' #define areYouCustomMsg '**' #define mMenuKeyMsg 'SK' // MENU resource structures typedef struct { char iconID; char keyEq; char mark; Style textStyle; } stdItemData, *StdItemDataPtr; // Menubar structures typedef struct { short offsetToLastMenu; short HorizRtEdgeLastmenu; short dummy; struct { MenuHandle theMenu; short HorizRtEdge; } menuIDList[100]; } MBarRec, *MBarRecPtr; // MenuKey result structure typedef struct { union { long L; short menuID, itemNum; } match; } menuMatch; pascal Boolean IsCustomMenu(MenuHandle menu) { // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // x // x IsCustomMenu returns true if hMenu is controlled by a custom MDEF. This relies on my // x convention of returning the customDefProcSig constant in the rect parameter: this obtuse // x convention should be unique enough that only my custom MDEFs behave this way. // x // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Point zeroPoint = { 0, 0 }; char state; Handle proc; Rect dummy; short dummyInt; MenuDefUPP mdef; proc = (*menu)->menuProc; state = HGetState(proc); HLock(proc); dummy.top = dummy.left = 0; mdef = (MenuDefUPP)NewRoutineDescriptor((ProcPtr)*proc, uppMenuDefProcInfo, kM68kISA); CallMenuDefProc(mdef, areYouCustomMsg, menu, &dummy, zeroPoint, &dummyInt); DisposeRoutineDescriptor(mdef); HSetState(proc, state); return *(long *)&dummy == customDefProcSig; } pascal long PowerMenuKey(long theMessage, short theModifiers, MenuHandle hMenu) { Point thePoint = *(Point *)&theMessage; char state; Handle proc; Rect dummyRect; MenuDefUPP mdef; if (!hMenu || !IsCustomMenu(hMenu)) return MenuKey(theMessage & charCodeMask); else { proc = (*hMenu)->menuProc; state = HGetState(proc); HLock(proc); dummyRect.top = dummyRect.left = 0; mdef = (MenuDefUPP)NewRoutineDescriptor((ProcPtr)*proc, uppMenuDefProcInfo, kM68kISA); CallMenuDefProc(mdef, mMenuKeyMsg, hMenu, &dummyRect, thePoint, &theModifiers); DisposeRoutineDescriptor(mdef); HSetState(proc, state); return *(long *)&dummyRect; } } \ No newline at end of file diff --git a/Source/C/MiscellaneousUtils.c b/Source/C/MiscellaneousUtils.c new file mode 100644 index 0000000..9c1597d --- /dev/null +++ b/Source/C/MiscellaneousUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local variables: * lTimeInstalled = count of the number of times the task record has been installed * lTimeTask = Time Manager task record for calculating elapsed times * */ static short gTimeInstalled = 0; static long gStartTicks; static Boolean HandleAbortMouseDown(EventRecord *theEvent); static Boolean HandleAbortKeyDown(EventRecord *theEvent); /* * CheckAbort() * * Purpose: Scans the event queue for an aborting keypress * Inputs: none * Returns: true if we should abort * */ Boolean CheckAbort(JVDrawParamsHandle theParams) { static long gLastTime = 0; static short gCount = 0; Boolean aborted = false, QDxInstalled; ImageHandle theImage; EventRecord theEvent; EvQElPtr eventPtr; short sleepTime; Point newPoint; // get the proper sleep time: according to preferences if in foreground, or the // maximum if we're in the background or running as a screen saver if (gInBackground || gScreenSaver || gThePrefs.backgroundTime == bgMaximal) sleepTime = kSleepTime; else if (gThePrefs.backgroundTime == bgMinimal) sleepTime = 0; else sleepTime = 3; // if we're in screen saver mode, make sure we're frontmost if (gScreenSaver) EnsureFrontmost(); // if we're not in the background, ensure that we get at least 2 ticks of continuous // operation before giving up a full amount of time to others if (!gInBackground && (TickCount() - gLastTime) < 2) sleepTime = 0; PushPort(); MySetPort((CGrafPtr)FrontWindow()); QDxInstalled = GetQDxDispatchPatchState(); // get the next event; if sleepTime is zero, check event availability first if (sleepTime || EventAvail(everyEvent, &theEvent)) { // if we're in screen saver mode, and the mouse moved, quit immediately newPoint = GlobalMouse(); if (gSlideShow && gScreenSaver && (abs(newPoint.h - gScreenSaverPoint.h) > 2 || abs(newPoint.v - gScreenSaverPoint.v) > 2)) { SendQuitApplication(); aborted = true; } // otherwise, handle any pending events normally else while (WaitNextEvent(everyEvent - highLevelEventMask, &theEvent, sleepTime, nil)) { // dispatch the event as appropriate switch (theEvent.what) { case mouseDown: aborted = HandleAbortMouseDown(&theEvent); break; case keyDown: if (theEvent.message == kCreator) break; case autoKey: aborted = HandleAbortKeyDown(&theEvent); break; case updateEvt: if (theImage = FindImage((WindowPtr)theEvent.message)) { if (gDrawing && theImage == gDrawing && theParams && (*theParams)->on.port) { aborted = true; MySetPort((CGrafPtr)(*theImage)->window); BeginUpdate((*theImage)->window); UnionRgn((*theImage)->update, (*theImage)->window->visRgn, (*theImage)->update); EndUpdate((*theImage)->window); (*theImage)->flags |= ifNeedToRedraw; } else DeferImageUpdate(theImage); } else HandleUpdateEvent(&theEvent); break; case activateEvt: HandleActivateEvent(&theEvent); break; case osEvt: HandleOSEvent(&theEvent); break; } StartSpinning(); // if we got a pending button, abort (unless it's during offscreen draw of // user-controlled slide show) if (gPendingButton != -1) if (gPendingButton != kForwardButton || (theParams && (*theParams)->on.port)) aborted = true; } } else { if (!(gCount = (gCount + 1) & 0x1f) && !gInBackground) PPostEvent(keyDown, kCreator, &eventPtr); } SetQDxDispatchPatchState(QDxInstalled); PopPort(); if (sleepTime) gLastTime = TickCount(); return aborted; } static Boolean HandleAbortMouseDown(EventRecord *theEvent) { Boolean aborted = false; // if we're in screen saver mode, always abort if (gSlideShow && gScreenSaver) { SendQuitApplication(); return true; } // handle dialog events properly; if button 3 was hit on the progress dialog, // we abort the drawing if (IsDialogEvent(theEvent)) { DialogPtr theDialog; short itemHit; StopSpinning(&qd.arrow); if (DialogSelect(theEvent, &theDialog, &itemHit) && GetWRefCon(theDialog) == kProgressDialogID && itemHit == progressCancel) aborted = true; // otherwise, do it the hard way.... } else { WindowPtr theWindow; short thePart = FindWindow(theEvent->where, &theWindow); // if a slide show is happening and the mouse was clicked in a // non-floating window, toggle the visible state of the slide show controls if (gSlideShow && WindowKind(theWindow) != floatingWindowKind) { theWindow = GetSlideControlsWindow(); if (!theWindow) { if (OpenSlideControls() == noErr) ChangeActive(GetSlideControlsWindow()); } else CloseSlideControls(); // otherwise, track dragging and menus as normal; check specially for clicks in // the slide show controls floating window, and beep about everything else } else { switch (thePart) { case inDrag: StopSpinning(&qd.arrow); HandleDragClick(theEvent, theWindow); break; case inMenuBar: StopSpinning(&qd.arrow); if (gMenuVisible) HandleMenuClick(theEvent); break; case inGrow: case inContent: if (theWindow == GetSlideControlsWindow()) { StopSpinning(&qd.arrow); HandleSlideControlsClick(theEvent->where, theEvent->modifiers, false); break; } default: SysBeep(1); break; } } } return aborted; } static Boolean HandleAbortKeyDown(EventRecord *theEvent) { uchar theChar = theEvent->message & charCodeMask; Boolean aborted = false; DialogPtr theDialog; for (theDialog = FWFrontWindow(); theDialog; theDialog = NextWindow(theDialog)) if (GetWRefCon(theDialog) == kProgressDialogID) break; // if we're in screen saver mode, always abort if (gSlideShow && gScreenSaver) { SendQuitApplication(); return true; } // for cmd-0, cmd-`, and cmd-\, dispatch to the standard menu handler; // if cmd-. set the proper abort flag if ((theEvent->modifiers & cmdKey) && theChar != '.') { if (theChar == '0' || theChar == '`' || theChar == '\\' || theChar == 'Q' || theChar == 'q') { HandleMenuChoice(PowerMenuKey(theEvent->message, theEvent->modifiers, GetMHandle(rFileMenu))); if (gDone) aborted = true; } } // if escape, set the proper abort flag else if (((theEvent->modifiers & cmdKey) && theChar == '.') || theChar == kEscapeChar) { // if the we're in a slide show & the stop button is disabled, simply abort if (gSlideShow == kPaused && GetSlideControlsWindow() && GetSlideControlButton(kStopButton) == disabled) aborted = 0x4d; else if (gSlideShow) HandleSlideControlsKey(theChar, theEvent->modifiers, false); else aborted = 0x4d; // if we're in a slide show, pass the key through the controls handler } else if (gSlideShow) HandleSlideControlsKey(theChar, theEvent->modifiers, false); if (aborted == 0x4d && theDialog) { PushPort(); MySetPort((CGrafPtr)theDialog); HandleDialogCancelKey(theDialog); aborted = true; PopPort(); } return aborted; } /* * StartTimer() * * Purpose: Starts a Time Manager task to calculate an elapsed time * Inputs: none * Returns: nothing * */ void StartTimer(void) { if (++gTimeInstalled != 1) return; gStartTicks = TickCount(); } /* * StopTimer() * * Purpose: Stops the Time Manager task to calculate an elapsed time * Inputs: none * Returns: the elapsed time, in milliseconds * */ long StopTimer(void) { if (--gTimeInstalled) return 0L; return ((TickCount() - gStartTicks) * 1000L / 60L); } /* * DirName(dirID, vRefNum, s) * * Purpose: Returns the name of the directory given by the dirID and vRefNum * Inputs: dirID = the directory ID of the directory * vRefNum = the vRef of the directory * s = a pointer to a string to hold the final name * Returns: s * */ char *DirName(long dirID, short vRefNum, char *s) { Str255 directoryName; CInfoPBRec block; *s = 0; block.dirInfo.ioNamePtr = directoryName; block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID = dirID; block.dirInfo.ioVRefNum = vRefNum; block.dirInfo.ioFDirIndex = -1; if (PBGetCatInfo(&block, false) == noErr) { if (directoryName[0]) BlockMove(directoryName, s, directoryName[0] + 1); else s[0] = 0; } else s[0] = 0; return s; } /* * GetDirectoryID(dirID, vRefNum) * * Purpose: Gets the dirID of the given directory * Inputs: theSpec = pointer to the directory spec * theID = pointer to a long to store the ID * Returns: an OSErr describing what went wrong * */ OSErr GetDirectoryID(FSSpec *theSpec, long *theID) { CInfoPBRec block; Str255 fileName; OSErr theErr; block.hFileInfo.ioNamePtr = fileName; BlockMove(theSpec->name, fileName, *theSpec->name + 1); block.hFileInfo.ioVRefNum = theSpec->vRefNum; block.hFileInfo.ioFDirIndex = 0; block.hFileInfo.ioDirID = theSpec->parID; theErr = PBGetCatInfo(&block, false); if (theErr != noErr) return theErr; if (!(block.hFileInfo.ioFlAttrib & 0x10)) return errNotADirectory; *theID = block.dirInfo.ioDrDirID; return theErr; } /* * GetFullPath(theSpec, thePath) * * Purpose: Gets the full pathname from a given FSSpec * Inputs: theSpec = pointer to the directory spec * thePath = pointer to a handle to receive the path * Returns: an OSErr describing what went wrong * */ OSErr GetFullPath(FSSpec *theSpec, Handle *thePath) { OSErr theErr = noErr; Boolean isDirectory; long size, tempID; Str255 dirName; DirInfo block; theErr = GetDirectoryID(theSpec, &tempID); isDirectory = (theErr == noErr); *thePath = NewHandle(size = *theSpec->name); if (*thePath) { BlockMove(&theSpec->name[1], **thePath, *theSpec->name); block.ioDrParID = theSpec->parID; block.ioNamePtr = dirName; do { block.ioVRefNum = theSpec->vRefNum; block.ioFDirIndex = -1; block.ioDrDirID = block.ioDrParID; theErr = PBGetCatInfo((CInfoPBPtr)&block, false); if (theErr != noErr) { if (isDirectory) return noErr; break; } SetHandleSize(*thePath, size + 1 + *dirName); theErr = MemError(); if (theErr != noErr) break; BlockMove(**thePath, **thePath + *dirName + 1, size); size += 1 + *dirName; BlockMove(&dirName[1], **thePath, *dirName); *(**thePath + *dirName) = ':'; } while (block.ioDrDirID != 2); } else theErr = memFullErr; if ((theErr != noErr) && *thePath) { DisposeHandle(*thePath); *thePath = nil; } return theErr; } /* * ForceFolderUpdate(dirID, vRefNum) * * Purpose: Forces the Finder to update the directory information of the given folder * Inputs: dirID = the directory ID of the directory * vRefNum = the vRef of the directory * Returns: nothing * */ void ForceFolderUpdate(long dirID, short vRefNum) { CInfoPBRec block; block.hFileInfo.ioCompletion = nil; block.hFileInfo.ioNamePtr = nil; block.hFileInfo.ioVRefNum = vRefNum; block.hFileInfo.ioDirID = dirID; block.hFileInfo.ioFDirIndex = -1; PBGetCatInfo(&block, false); GetDateTime(&block.dirInfo.ioDrMdDat); PBSetCatInfo(&block, false); } /* * AddString(theString, theAddition) * * Purpose: Appends theAddition, a pascal string, to the pascal string theString * Inputs: theString = the destination string in pascal format * theAddition = the text of the addition * Returns: nothing * */ void AddString(StringPtr theString, StringPtr theAddition) { BlockMove((uchar *)theAddition + 1, theString + theString[0] + 1, *theAddition); *theString += *theAddition; } /* * AddCString(theString, theAddition, length) * * Purpose: Appends theAddition, a C string of length length, to the pascal string * theString * Inputs: theString = the destination string in pascal format * theAddition = the text of the addition * length = the length of the addition * Returns: nothing * */ void AddCString(StringPtr theString, char *theAddition, int length) { BlockMove(theAddition, theString + theString[0] + 1, length); *theString += length; } /* * AddNumber(theString, theNum) * * Purpose: Appends an ASCII representation of theNum to the pascal string theString * Inputs: theString = the destination string in pascal format * theNum = the number to append * Returns: nothing * */ void AddNumber(StringPtr theString, long theNum) { Str255 tempNum, theAddition; int i; NumToString(theNum, tempNum); *theAddition = 0; for (i = 1; i <= *tempNum; i++) { AddChar(theAddition, tempNum[i]); if ((*tempNum > 4) && (*tempNum != i) && (((*tempNum - i) % 3) == 0)) AddChar(theAddition, gThousandsSep); } AddString(theString, theAddition); } void StuffNumber(StringPtr theString, short theItem, long theNum) { Str32 tempNum, fixedNum; StringPtr src, dst; short j; NumToString(theNum, tempNum); src = &tempNum[1]; dst = &fixedNum[1]; *fixedNum = *tempNum; for (j = 1; j <= *tempNum; j++) { *dst++ = *src++; if ((*tempNum > 4) && (*tempNum != j) && (((*tempNum - j) % 3) == 0)) *dst++ = gThousandsSep, (*fixedNum)++; } StuffString(theString, theItem, fixedNum); } void StuffNumber0(StringPtr theString, short theItem, long theNum, short theLength) { Str32 tempNum; NumToString(theNum, tempNum); while (*tempNum < theLength) { BlockMove(&tempNum[1], &tempNum[2], 30); tempNum[1] = '0'; (*tempNum)++; } StuffString(theString, theItem, tempNum); } void StuffDepth(StringPtr theString, short theItem, short theDepth) { Str32 tempNum; if (theDepth > 32) theDepth -= 32; if (theDepth <= 8) NumToString(1L << theDepth, tempNum); else if (theDepth == 16) BlockMove(gString[strThousands], tempNum, *gString[strThousands] + 1); else BlockMove(gString[strMillions], tempNum, *gString[strMillions] + 1); StuffString(theString, theItem, tempNum); } void StuffString(StringPtr theString, short theItem, StringPtr addString) { Str255 tempStr; StringPtr src = &theString[1], dst = &tempStr[1], num = &addString[1]; short i, j, len = *theString; theItem += '0'; for (i = 0; i < len; i++) { if ((*src == '~') && (*(src+1) == theItem)) break; else *dst++ = *src++; } if (*src != '~') return; num = &addString[1]; for (j = 0; j < *addString; j++) *dst++ = *num++; src += 2, i += 2; for ( ; i < len; i++) *dst++ = *src++; *tempStr = len + *addString - 2; BlockMove(tempStr, theString, *tempStr + 1); } /* * GlobalMouse() * * Purpose: Gets the global coordinates of the mouse * Inputs: none * Returns: the mouse location in global coordinates * */ Point GlobalMouse(void) { Point thePoint; PushPort(); MySetPort(nil); GetMouse(&thePoint); LocalToGlobal(&thePoint); PopPort(); return thePoint; } \ No newline at end of file diff --git a/Source/C/MonitorUtils.c b/Source/C/MonitorUtils.c new file mode 100644 index 0000000..80ff111 --- /dev/null +++ b/Source/C/MonitorUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * MonitorInit() * * Purpose: Sets up the linked list of screen devices, and sets their inverse color * table resolutions to 5 bits per component * Inputs: none * Returns: nothing * */ void MonitorInit(void) { DeviceLoopDrawingUPP addDevice = NewDeviceLoopDrawingProc((ProcPtr)AddDevice); MonitorHandle theMonitor; GDHandle theDevice; if (!(theDevice = GetMainDevice())) FatalError(errNoDeviceInfo); if (!(theMonitor = gMainMonitor = NewMonitor(theDevice))) FatalError(errNoMemory); DeviceLoop(nil, addDevice, (long)&theMonitor, allDevices + singleDevices); DisposeRoutineDescriptor((UniversalProcPtr)addDevice); SetUpDevices(); KeepSpinning(); } /* * AddDevice(depth, deviceFlags, targetDevice, userData) * * Purpose: DeviceLoop routine to add the current device to the linked list * Inputs: depth = depth of the device * deviceFlags = device flags for the device * targetDevice = handle to the target device * userData = a refCon we can use * Returns: nothing * */ pascal void AddDevice(short depth, short deviceFlags, GDHandle targetDevice, MonitorHandle *theMonitor) { #if applec #pragma unused(depth, deviceFlags) #endif if (targetDevice != (*gMainMonitor)->device) { if ((**theMonitor)->next = NewMonitor(targetDevice)) *theMonitor = (**theMonitor)->next; } } /* * NewMonitor() * * Purpose: Allocates and initializes a new monitor record based on the given device * Inputs: theDevice = handle to the new device * Returns: a pointer to the new monitor record * */ MonitorHandle NewMonitor(GDHandle theDevice) { MonitorHandle theMonitor; Rect theRect; if (theMonitor = (MonitorHandle)NewHandle(sizeof(MonitorItem))) { if ((*theMonitor)->gray = NewRgn()) { if ((*theMonitor)->screen = NewRgn()) { (*theMonitor)->next = nil; (*theMonitor)->device = theDevice; (*theMonitor)->oldres = (*theDevice)->gdResPref; (*theMonitor)->color = IsColorDevice(theDevice); (*theMonitor)->depth = MonitorDepth(theMonitor); (*theMonitor)->full = false; theRect = (*theMonitor)->rect = (*theDevice)->gdRect; RectRgn((*theMonitor)->screen, &theRect); SectRgn((*theMonitor)->screen, GetGrayRgn(), (*theMonitor)->gray); return theMonitor; } DisposeHandle((Handle)(*theMonitor)->gray); } DisposeHandle((Handle)theMonitor); } return nil; } /* * MonitorChanged() * * Purpose: Checks to see if any monitors have changed depth/greys * Inputs: none * Returns: a pointer to the changed monitor, or nil if everything is the same * */ MonitorHandle MonitorChanged(void) { MonitorHandle theMonitor; Boolean color; short depth; for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { color = IsColorDevice((*theMonitor)->device); depth = MonitorDepth(theMonitor); if (((*theMonitor)->color != color) || ((*theMonitor)->depth != depth)) { (*theMonitor)->color = color; (*theMonitor)->depth = depth; return theMonitor; } } return nil; } /* * SetUpDevices() * * Purpose: Restores the new inverse table resolutions on the various devices * Inputs: none * Returns: nothing * */ void SetUpDevices(void) { MonitorHandle theMonitor; for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { /*(*(*theMonitor)->device)->gdResPref = 5; if ((*(*theMonitor)->device)->gdITable) (*(*(*theMonitor)->device)->gdITable)->iTabSeed = GetCTSeed(); GDeviceChanged((*theMonitor)->device);*/ } } /* * ResetDevices() * * Purpose: Restores the original inverse table resolutions on the various devices * Inputs: none * Returns: nothing * */ void ResetDevices(void) { MonitorHandle theMonitor; if (!gMenuVisible && !(*gMainMonitor)->full) UnhideMenuBar(); for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) if ((*theMonitor)->full) NormalScreen(theMonitor); } /* * ResetColors() * * Purpose: Restores the colors of all active screens to their original CLUTs * Inputs: none * Returns: nothing * */ void ResetColors(void) { MonitorHandle theMonitor; RgnHandle theRgn; if (gInBackground) return; if (theRgn = NewRgn()) { for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { if (!(*(*theMonitor)->device)->gdType) { RestoreDeviceClut((*theMonitor)->device); UnionRgn(theRgn, (*theMonitor)->gray, theRgn); } } if (!EmptyRgn(theRgn)) { LMSetPaintWhite(true); PaintBehind((WindowPeek)GetFirstWindow(), theRgn); LMSetPaintWhite(false); PaintOne(nil, theRgn); LMSetPaintWhite(true); } DisposeRgn(theRgn); } } /* * FullScreen(theMonitor) * * Purpose: Fixes up theMonitor to allow full-screen windows * Inputs: theMonitor = pointer to the monitor we're interested in, or nil for all * Returns: nothing * */ void FullScreen(MonitorHandle theMonitor) { RgnHandle updateRgn; if (!theMonitor) { for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) FullScreen(theMonitor); return; } if ((*theMonitor)->full) return; UnionRgn(GetGrayRgn(), (*theMonitor)->screen, GetGrayRgn()); if (theMonitor == gMainMonitor && gInBackground && (updateRgn = GetMenuRgn())) DiffRgn(GetGrayRgn(), updateRgn, GetGrayRgn()); if (updateRgn = NewRgn()) { DiffRgn((*theMonitor)->screen, (*theMonitor)->gray, updateRgn); PaintOne((WindowPeek)FrontWindow(), updateRgn); PaintBehind((WindowPeek)FrontWindow(), updateRgn); CalcVis((WindowPeek)FrontWindow()); CalcVisBehind((WindowPeek)FrontWindow(), updateRgn); DisposeRgn(updateRgn); if (theMonitor == gMainMonitor && !gInBackground) { LMSetMBarHeight(0); gMenuVisible = false; RestoreMenuArea(); } (*theMonitor)->full = true; } } /* * NormalScreen(theMonitor) * * Purpose: Fixes up theMonitor to remove the effects of FullScreen * Inputs: theMonitor = pointer to the monitor we're interested in, or nil for all * Returns: nothing * */ void NormalScreen(MonitorHandle theMonitor) { Boolean oldMenuVis = gMenuVisible; RgnHandle updateRgn; GrafPort tempPort; if (!theMonitor) { for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) NormalScreen(theMonitor); return; } if (!(*theMonitor)->full) return; if (updateRgn = NewRgn()) { if (theMonitor == gMainMonitor) SaveMenuArea(); DiffRgn((*theMonitor)->screen, (*theMonitor)->gray, updateRgn); PushPort(); OpenPort(&tempPort); CopyRgn(GetGrayRgn(), tempPort.visRgn); MySetPort((CGrafPtr)&tempPort); RGBForeColor(&gBlack); PaintRgn(updateRgn); ClosePort(&tempPort); PopPort(); DiffRgn(GetGrayRgn(), updateRgn, GetGrayRgn()); CalcVis((WindowPeek)FrontWindow()); CalcVisBehind((WindowPeek)FrontWindow(), updateRgn); DisposeRgn(updateRgn); if (theMonitor == gMainMonitor) { LMSetMBarHeight(gMenuHeight); gMenuVisible = true; AdjustMenus(); DrawMenuBar(); NudgeWindoids(); } } (*theMonitor)->full = false; } /* * NudgeWindoids() * * Purpose: Check all windoids to be sure they're not under the menubar * Inputs: none * Returns: nothing * */ void NudgeWindoids(void) { WindowPtr theWindow = GetFirstWindow(); Rect theRect, menuRect, tempRect; menuRect = (*gMainMonitor)->rect; menuRect.bottom = menuRect.top + GetMBarHeight(); while (theWindow) { if (WindowKind((WindowPtr)theWindow) == floatingWindowKind) { theRect = theWindow->portRect; theRect.top -= gTitleBarHeight * 2 / 3; GlobalRect(&theRect, theWindow); if (SectRect(&theRect, &menuRect, &tempRect)) { theRect.top = GetMBarHeight() + gTitleBarHeight * 2 / 3; MoveWindow(theWindow, theRect.left, theRect.top, false); } } theWindow = NextWindow(theWindow); } } /* * UnhideMenuBar() * * Purpose: Displays the menubar on the main screen, if it's currently full-screen * Inputs: none * Returns: nothing * */ void UnhideMenuBar(void) { Boolean oldMenuVis = gMenuVisible; RgnHandle menuRgn = GetMenuRgn(); if (!(*gMainMonitor)->full || gMenuVisible) return; SaveMenuArea(); DiffRgn(GetGrayRgn(), menuRgn, GetGrayRgn()); CalcVis((WindowPeek)FrontWindow()); CalcVisBehind((WindowPeek)FrontWindow(), menuRgn); LMSetMBarHeight(gMenuHeight); gMenuVisible = true; if (oldMenuVis) MyInvalMenuBar(); else { AdjustMenus(); DrawMenuBar(); } } /* * RehideMenuBar() * * Purpose: Removes the menu bar from the main screen, if it's currently full-screen * Inputs: none * Returns: nothing * */ void RehideMenuBar(void) { RgnHandle menuRgn = GetMenuRgn(); if (!(*gMainMonitor)->full || !gMenuVisible || gInBackground) return; UnionRgn(GetGrayRgn(), menuRgn, GetGrayRgn()); PaintOne((WindowPeek)FrontWindow(), menuRgn); PaintBehind((WindowPeek)FrontWindow(), menuRgn); CalcVis((WindowPeek)FrontWindow()); CalcVisBehind((WindowPeek)FrontWindow(), menuRgn); LMSetMBarHeight(0); gMenuVisible = false; RestoreMenuArea(); } /* * FrontWindowRgn(theRgn) * * Purpose: Finds the frontmost window that lies unobscured in theRgn * Inputs: theRgn = the region of interest, in global coordinates * Returns: a pointer to the window found, or nil if none qualify * */ WindowPtr FrontWindowRgn(RgnHandle theRgn) { WindowPtr theWindow = FWFrontWindow(); WindowPtr theResult = nil; RgnHandle testRgn; if (testRgn = NewRgn()) { for ( ; theWindow; theWindow = NextWindow(theWindow)) { CopyRgn(theWindow->visRgn, testRgn); GlobalRgn(testRgn, theWindow); SectRgn(theRgn, testRgn, testRgn); if (EqualRgn(theRgn, testRgn)) { theResult = theWindow; break; } else if (!EmptyRgn(testRgn)) break; } DisposeRgn(testRgn); } return theResult; } /* * GetMenuRgn() * * Purpose: Calculates the region occupied by the menubar * Inputs: none * Returns: a handle to the region of the menu bar * */ RgnHandle GetMenuRgn(void) { static RgnHandle gMenuRgn = nil; if (!gMenuRgn) { gMenuRgn = NewRgn(); gMenuHeight = GetMBarHeight(); } if (gMenuRgn) SetRectRgn(gMenuRgn, (*gMainMonitor)->rect.left, (*gMainMonitor)->rect.top, (*gMainMonitor)->rect.right, (*gMainMonitor)->rect.top + gMenuHeight); return gMenuRgn; } /* * GetActiveRect(theMonitor, theRect) * * Purpose: Determines the active area of the monitor, with or without menu bar as * appropriate * Inputs: theMonitor = a handle to the monitor record * theRect = a pointer to the destination rectangle * Returns: nothing * */ void GetActiveRect(MonitorHandle theMonitor, Rect *theRect) { if ((theMonitor != gMainMonitor) || !gMenuVisible) *theRect = (*theMonitor)->rect; else *theRect = (*(*theMonitor)->gray)->rgnBBox; } /* * GetMinMaxMonitor(theImage) * * Purpose: Calculates the shallowest and deepest monitors intersecting the given * image's window * Inputs: theImage = a pointer to the image * Returns: nothing * */ void GetMinMaxMonitor(ImageHandle theImage) { MonitorHandle theMonitor, deepMon = nil, shallowMon = nil; ushort pass, depth, shallowest = 100, deepest = 0; Rect winRect, tmpRect; if (!WindowVisible((*theImage)->window)) { if (!(*theImage)->dmon) (*theImage)->dmon = gMainMonitor; if (!(*theImage)->smon) (*theImage)->smon = gMainMonitor; return; } for (pass = 1; pass <= 2; pass++) { winRect = (pass == 1) ? (*GetContRgn((*theImage)->window))->rgnBBox : (*GetStrucRgn((*theImage)->window))->rgnBBox; InsetRect(&winRect, 1, 1); for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { if (SectRect(&winRect, &(*theMonitor)->rect, &tmpRect)) { depth = (*theMonitor)->depth; if (depth > deepest) { deepest = depth; deepMon = theMonitor; } if (depth < shallowest) { shallowest = depth; shallowMon = theMonitor; } } } if (deepMon && shallowMon) break; } if (deepMon && shallowMon) { (*theImage)->dmon = deepMon; (*theImage)->smon = shallowMon; } else if (deepMon) (*theImage)->dmon = (*theImage)->smon = deepMon; else if (shallowMon) (*theImage)->dmon = (*theImage)->smon = shallowMon; else (*theImage)->dmon = (*theImage)->smon = gMainMonitor; } /* * GetDeepMonitor(pickColor) * * Purpose: Returns a pointer to the current deepest monitor * Inputs: pickColor = flag: true to pick color monitors first * Returns: a MonitorHandle pointing to the deepest monitor * */ MonitorHandle GetDeepMonitor(Boolean pickColor) { ushort depth, deepest = 0, color = pickColor; MonitorHandle theMonitor, deepMon = nil; for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { depth = (*theMonitor)->depth; if ((depth > deepest) || ((depth == deepest) && ((pickColor && !color) || (!pickColor && color)))) { deepest = depth; deepMon = theMonitor; color = (*theMonitor)->color; } } return deepMon; } /* * GetBigMonitor(pickColor) * * Purpose: Returns a handle to the current biggest monitor * Inputs: pickColor = flag: true to pick color monitors first * Returns: a MonitorHandle pointing to the biggest monitor * */ MonitorHandle GetBigMonitor(Boolean pickColor) { ulong biggest = 0, size, color = pickColor; MonitorHandle theMonitor, bigMon = nil; for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { size = (long)Height(&(*theMonitor)->rect) * (long)Width(&(*theMonitor)->rect); if ((size > biggest) || ((size == biggest) && ((pickColor && !color) || (!pickColor && color)))) { biggest = size; bigMon = theMonitor; color = (*theMonitor)->color; } } return bigMon; } /* * GetImageMonitor(theImage) * * Purpose: Returns a pointer to the deepest monitor intersected by the image window * Inputs: theImage = pointer to the image we're interested in * Returns: a MonitorHandle of the deepest intersecting monitor * */ MonitorHandle GetImageMonitor(ImageHandle theImage) { MonitorHandle theMonitor, deepMon = nil; ushort depth, deepest = 0; Rect theRect, tmpRect; if (!theImage || !(*theImage)->window) return nil; theRect = (*theImage)->wrect; GlobalRect(&theRect, (*theImage)->window); for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { if (SectRect(&theRect, &(*theMonitor)->rect, &tmpRect)) { depth = (*theMonitor)->depth; if (depth > deepest) { deepest = depth; deepMon = theMonitor; } } } return deepMon; } /* * GetMostDevice(theRect) * * Purpose: Returns a pointer to the monitor containing the most area of the window * Inputs: theRect = pointer to a global rectangle * Returns: a MonitorHandle of the relevant intersecting monitor * */ MonitorHandle GetMostDevice(Rect *theRect) { MonitorHandle theMonitor, mostMon = gMainMonitor; long area, largest = 0; Rect tmpRect; for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { SectRect(&(*theMonitor)->rect, theRect, &tmpRect); area = (long)Width(&tmpRect) * (long)Height(&tmpRect); if (area > largest) { largest = area; mostMon = theMonitor; } } return mostMon; } \ No newline at end of file diff --git a/Source/C/PICT.c b/Source/C/PICT.c new file mode 100644 index 0000000..1f2e59e --- /dev/null +++ b/Source/C/PICT.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif typedef struct PICTPrivates { Rect qdRect; long totalLines; } PICTPrivates, *PICTPrivatesPtr, **PICTPrivatesHandle; /* * Local variables: * lPICTImage = pointer to the image for use when extracting PICT information * lPICTPreview = handle to the preview image, if one was requested for saving * */ static Handle gPICTComments; static Rect gPICTSrcRect, gPICTDstRect; static ImageHandle gPICTImage; static JVDrawParamsHandle gPICTParams; static long gTotalLines, gCurrentLines; static Boolean gHasObjects; static StdPixUPP gProgressPixProc = nil, gAddColorsPixProc, gInitPixProc; static QDBitsUPP gDummyBitsProc, gInitBitsProc; static QDTextUPP gDummyTextProc, gInitTextProc; static QDLineUPP gDummyLineProc, gInitLineProc; static QDRectUPP gDummyRectProc, gInitRectProc; static QDRRectUPP gDummyRRectProc, gInitRRectProc; static QDOvalUPP gDummyOvalProc, gInitOvalProc; static QDArcUPP gDummyArcProc, gInitArcProc; static QDPolyUPP gDummyPolyProc, gInitPolyProc; static QDRgnUPP gDummyRgnProc, gInitRgnProc; static void InitPICTUPPs(void); static pascal void ProgressPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags); static pascal void AddColorsPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags); static pascal void InitPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short callOldBits); static pascal void InitBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask); static pascal void InitTextProc(short count, const void *textAddr, Point numer, Point denom); static pascal void InitLineProc(Point newPt); static pascal void InitRectProc(GrafVerb verb, const Rect *r); static pascal void InitRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, short ovalHeight); static pascal void InitOvalProc(GrafVerb verb, const Rect *r); static pascal void InitArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle); static pascal void InitPolyProc(GrafVerb verb, PolyHandle poly); static pascal void InitRgnProc(GrafVerb verb, RgnHandle rgn); static pascal void DummyBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask); static pascal void DummyTextProc(short count, const void *textAddr, Point numer, Point denom); static pascal void DummyLineProc(Point newPt); static pascal void DummyRectProc(GrafVerb verb, const Rect *r); static pascal void DummyRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, short ovalHeight); static pascal void DummyOvalProc(GrafVerb verb, const Rect *r); static pascal void DummyArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle); static pascal void DummyPolyProc(GrafVerb verb, PolyHandle poly); static pascal void DummyRgnProc(GrafVerb verb, RgnHandle rgn); /* * idPICT(theData, theSize) * * Purpose: Attempts to identify an image as a PICT * Inputs: theData = pointer to the loaded data * theSize = size of the loaded data * Returns: true for a positive PICT ID * */ Boolean idPICT(uchar *theData, long theSize, short refNum, FSSpec *theSpec) { #if applec #pragma unused(refNum, theSpec) #endif ushort *theShort = (ushort *)(theData + kHeaderSize + 10); PicPtr thePicture = (PicPtr)(theData + kHeaderSize); if (theSize < kHeaderSize + 12) return false; if (Width(&thePicture->picFrame) > 0 && Height(&thePicture->picFrame) > 0) { while (!*theShort) theShort++; if (*theShort == 0x0011 || *theShort == 0x1101) return true; } return false; } /* * OpenPICT(theImage) * * Purpose: Initializes the image record for a PICT image * Inputs: theImage = image record for the PICT image * Returns: nothing * */ OSErr OpenPICT(ImageHandle theImage) { Fixed hRes = 0x480000L, vRes = 0x480000L; Rect *theRect, fullQRect; OSErr theErr = noErr; ushort *theShort; uchar *theData; Str63 theDesc; if (!((*theImage)->privateData = NewHandleClear(sizeof(PICTPrivates)))) return memFullErr; theData = (uchar *)*(*theImage)->data; theShort = (ushort *)(theData + 10); theRect = (Rect *)(theData + 2); (*(PICTPrivatesHandle)(*theImage)->privateData)->qdRect = (*theImage)->qrect = *theRect; while (!*theShort) theShort++; if (*theShort == 0x0011 && theShort[2] == 0x0c00 && theShort[3] == 0xfffe) { theRect = (Rect *)(theShort + 9); hRes = *(long *)(theShort + 5); vRes = *(long *)(theShort + 7); } (*theImage)->grect = *theRect; if (Width(&(*theImage)->grect) <= 0 || Height(&(*theImage)->grect) <= 0 || Width(&(*theImage)->qrect) <= 0 || Height(&(*theImage)->qrect) <= 0) return gIntError = errCorruptImage, codecBadDataErr; GetImageInfo(theImage); fullQRect = (*theImage)->grect; fullQRect.left = Fix2Long(FixMul(FixDiv(0x480000L, hRes), Long2Fix(fullQRect.left))); fullQRect.right = Fix2Long(FixMul(FixDiv(0x480000L, hRes), Long2Fix(fullQRect.right))); fullQRect.top = Fix2Long(FixMul(FixDiv(0x480000L, vRes), Long2Fix(fullQRect.top))); fullQRect.bottom = Fix2Long(FixMul(FixDiv(0x480000L, vRes), Long2Fix(fullQRect.bottom))); (*theImage)->crect = (*theImage)->qrect; MapRect(&(*theImage)->crect, &fullQRect, &(*theImage)->grect); (*theImage)->compression = (*theImage)->desc.cType; if ((*theImage)->desc.height) if (Height(&(*theImage)->crect) > (*theImage)->desc.height) (*theImage)->flags |= ifBanded; if ((*theImage)->crect.right < ((*theImage)->grect.right - 5) || (*theImage)->crect.left > ((*theImage)->grect.left + 5) || (*theImage)->crect.bottom < ((*theImage)->grect.bottom - 5) || (*theImage)->crect.top > ((*theImage)->grect.top + 5)) (*theImage)->flags |= ifCropped; /* if ((*theImage)->compression == kJPEGCompression && !gHasObjects) { if (Height(&(*theImage)->crect) > (*theImage)->desc.height) (*theImage)->flags |= ifBanded; if ((Width(&(*theImage)->crect) < (*theImage)->desc.width) || (Height(&(*theImage)->crect) < (*theImage)->desc.height)) (*theImage)->flags |= ifCropped; }*/ /* Old mechanism for detecting cropping vs. scaled DPI //--- deal with cropped images?? if ((*theData)->compressionType == 'jpeg' && !gHasObjects) { if (Height(&(*theImage)->crect) > (*theImage)->desc.height) (*theImage)->flags |= ifBanded; if ((Width(&(*theImage)->crect) < (*theImage)->desc.width) || (Height(&(*theImage)->crect) < (*theImage)->desc.height)) (*theImage)->flags |= ifCropped; if (Cropped(theImage) && !Banded(theImage)) { Rect crect = (*theImage)->crect, grect; MySetRect(&grect, 0, 0, (*theImage)->desc.width, (*theImage)->desc.height); MapRect(&crect, &(*theImage)->grect, &(*theImage)->qrect); MapRect(&crect, &lPICTDstRect, &lPICTSrcRect); if (crect.right > grect.right) crect.right = grect.right; if (crect.left < grect.left) crect.left = grect.left; if (crect.bottom > grect.bottom) crect.bottom = grect.bottom; if (crect.top < grect.top) crect.top = grect.top; (*theImage)->grect = grect; theErr = DoSetImageBounds(theImage, &grect); (*theImage)->crect = crect; if (EqualSizeRect(&crect, &grect)) (*theImage)->flags &= ~ifCropped; } } */ if (!(*theImage)->ipalette && ((*theImage)->depth == 36 || (*theImage)->depth == 40)) { (*theImage)->ipalette = NewPalette(1L << ((*theImage)->depth - 32), nil, pmTolerant, 0); if ((*theImage)->ipalette) CopyPalette(GreyPalette((*theImage)->depth - 32), (*theImage)->ipalette, 0, 0, 256); } if ((*theImage)->compression == 'raw ') (*theImage)->compression = 0L; if ((*theImage)->compression) { BlockMove((*theImage)->desc.name, theDesc, *(*theImage)->desc.name + 1); AddString(theDesc, gString[strQuality]); StuffNumber(theDesc, 1, (*theImage)->desc.spatialQuality >> 8); StuffNumber0(theDesc, 2, (((*theImage)->desc.spatialQuality & 0xff) * 100) >> 8, 2); } else BlockMove(gString[strUncompressed], theDesc, *gString[strUncompressed] + 1); BlockMove(theDesc, (*theImage)->compressionDesc, *theDesc + 1); return theErr; } /* * DrawPICT(theImage, theGWorld, srcRect, dstRect, dither, progProc) * * Purpose: Draws the PICT image within its cropping rectange in the proper window * Inputs: theImage = image record for the PICT image * theGWorld = the destination GWorld to draw into * srcRect = the source rectangle * dstRect = the destination rectangle * dstRgn = the destination clipping region * dither = flag: true if we should dither this guy * progProc = the progress procedure record to be used * Returns: nothing * */ OSErr DrawPICT(Handle theHandle, JVDrawParamsHandle theParams) { Rect globRect = (*theParams)->bounds; char hState = HGetState(theHandle); OSErr theErr; if (!gProgressPixProc) InitPICTUPPs(); ((CGrafPtr)qd.thePort)->grafProcs->newProc1 = (UniversalProcPtr)gProgressPixProc; gPICTParams = theParams; gTotalLines = (*(PICTPrivatesHandle)(*theParams)->privateData)->totalLines; gCurrentLines = 0; PushPort(); ClipRect(&globRect); RGBForeColor(&gBlack); RGBBackColor(&gWhite); HLock(theHandle); KeepSpinning(); if (gQTVersion) theErr = DrawTrimmedPicture((PicHandle)theHandle, &globRect, qd.thePort->visRgn, false, nil); else DrawPicture((PicHandle)theHandle, &globRect), theErr = noErr; if ((*theParams)->progress.aborted) theErr = codecAbortErr; KeepSpinning(); HSetState(theHandle, hState); PopPort(); return theErr; } /* * ProgressPixProc(src, srcRect, matrix, mode, mask, matte, matteRect, callOldBits) * * Purpose: Routine called when a compressed PixMap is found in a PICT; we * intercept it and call FDecompressImage, making the progress updates * work to some extent.... * Inputs: src = the compressed PixMap * srcRect = the rectangle of the image in the source coordinates * matrix = the transformation matrix * mode = the drawing mode * mask = the output masking region * matte = the output matte, described as a PixMap * matteRect = the bounding rectangle for the output matte * callOldBits = flag saying if we should call the old routine * Returns: nothing * */ pascal void ProgressPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags) { PixMapHandle dst = GetGWorldPixMap((CGrafPtr)qd.thePort); NestedProgress theProc = (*gPICTParams)->progress; ImageDescriptionHandle theDesc; ICMProgressProcRecord progProc; ICMDataProcRecord dataProc; OSErr theErr; long bufSize; Ptr theData; if ((*gPICTParams)->progress.aborted || ((*gPICTParams)->progress.aborted = CheckAbort(gPICTParams))) return; theErr = GetCompressedPixMapInfo(src, &theDesc, &theData, &bufSize, &dataProc, &progProc); if (theErr == noErr) { KeepSpinning(); (*gPICTParams)->progress.begin = FixRatio(gCurrentLines, gTotalLines); (*gPICTParams)->progress.begin = theProc.begin + FixMul((*gPICTParams)->progress.begin, theProc.end - theProc.begin); (*gPICTParams)->progress.end = FixRatio(gCurrentLines + Height(srcRect), gTotalLines); (*gPICTParams)->progress.end = theProc.begin + FixMul((*gPICTParams)->progress.end, theProc.end - theProc.begin); if ((*gPICTParams)->progress.prog.progressProc) CallICMProgressProc((*gPICTParams)->progress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, (*gPICTParams)->progress.prog.progressRefCon); FixBits((CGrafPtr)qd.thePort, true); InstallQDxDispatchPatch(true); FDecompressImage(StripAddress(theData), theDesc, dst, srcRect, matrix, mode, mask, &matte, matteRect, codecHighQuality, anyCodec, bufSize, &dataProc, (ICMProgressProcRecordPtr)&theProc); RemoveQDxDispatchPatch(); FixBits((CGrafPtr)qd.thePort, false); if ((*gPICTParams)->progress.prog.progressProc && !(*gPICTParams)->progress.aborted) CallICMProgressProc((*gPICTParams)->progress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, (*gPICTParams)->progress.prog.progressRefCon); KeepSpinning(); (*gPICTParams)->progress.begin = theProc.begin; (*gPICTParams)->progress.end = theProc.end; gCurrentLines += Height(srcRect); } else StdPix(src, srcRect, matrix, mode | 0x80, mask, matte, matteRect, flags); if (gSlideShow && !(*gPICTParams)->progress.aborted) (*gPICTParams)->progress.aborted = CheckAbort(gPICTParams); } /* * LoadPICT(theFile, theImage) * * Purpose: Allocates memory and loads the PICT image in * Inputs: theFile = the input file * theImage = image record * Returns: nothing * */ OSErr LoadPICT(short theFile, ImageHandle theImage) { OSErr theErr = noErr; long theSize; KeepSpinning(); GetEOF(theFile, &theSize); if ((theSize -= kHeaderSize) < 0) return errCorruptImage, codecBadDataErr; if (!MakeMemAvailable(theSize)) return gIntError = errNoLoadMemory, memFullErr; if ((*theImage)->data = NewHandle(theSize)) { SetFPos(theFile, fsFromStart, kHeaderSize); HLock((*theImage)->data); SpinIndef(); theErr = FSRead(theFile, &theSize, *(*theImage)->data); KeepSpinning(); HUnlock((*theImage)->data); if (theErr == noErr) return theErr; else DisposeHandle((*theImage)->data); gIntError = errCantReadFile; } else gIntError = errNoLoadMemory, theErr = memFullErr; return theErr; } static void InitPICTUPPs(void) { gProgressPixProc = NewStdPixProc((ProcPtr)ProgressPixProc); gAddColorsPixProc = NewStdPixProc((ProcPtr)AddColorsPixProc); gInitPixProc = NewStdPixProc((ProcPtr)InitPixProc); gInitBitsProc = NewQDBitsProc((ProcPtr)InitBitsProc); gInitTextProc = NewQDTextProc((ProcPtr)InitTextProc); gInitLineProc = NewQDLineProc((ProcPtr)InitLineProc); gInitRectProc = NewQDRectProc((ProcPtr)InitRectProc); gInitRRectProc = NewQDRRectProc((ProcPtr)InitRRectProc); gInitOvalProc = NewQDOvalProc((ProcPtr)InitOvalProc); gInitArcProc = NewQDArcProc((ProcPtr)InitArcProc); gInitPolyProc = NewQDPolyProc((ProcPtr)InitPolyProc); gInitRgnProc = NewQDRgnProc((ProcPtr)InitRgnProc); gDummyBitsProc = NewQDBitsProc((ProcPtr)DummyBitsProc); gDummyTextProc = NewQDTextProc((ProcPtr)DummyTextProc); gDummyLineProc = NewQDLineProc((ProcPtr)DummyLineProc); gDummyRectProc = NewQDRectProc((ProcPtr)DummyRectProc); gDummyRRectProc = NewQDRRectProc((ProcPtr)DummyRRectProc); gDummyOvalProc = NewQDOvalProc((ProcPtr)DummyOvalProc); gDummyArcProc = NewQDArcProc((ProcPtr)DummyArcProc); gDummyPolyProc = NewQDPolyProc((ProcPtr)DummyPolyProc); gDummyRgnProc = NewQDRgnProc((ProcPtr)DummyRgnProc); } /* * GetImageInfo(theImage) * * Purpose: Retrieves the image description and CLUT from a given PICT * Inputs: theImage = image record for the PICT image * Returns: nothing * */ void GetImageInfo(ImageHandle theImage) { char hState = HGetState((*theImage)->data); Rect theRect = (*theImage)->qrect; CQDProcs theProcs, *oldProcs; gPICTImage = theImage; gPICTComments = nil; gTotalLines = 0; gHasObjects = false; PushPort(); MySetPort(gGenericGWorld); SetStdCProcs(&theProcs); if (!gProgressPixProc) InitPICTUPPs(); theProcs.newProc1 = (UniversalProcPtr)gInitPixProc; theProcs.bitsProc = gInitBitsProc; theProcs.textProc = gInitTextProc; theProcs.lineProc = gInitLineProc; theProcs.rectProc = gInitRectProc; theProcs.rRectProc = gInitRRectProc; theProcs.ovalProc = gInitOvalProc; theProcs.arcProc = gInitArcProc; theProcs.polyProc = gInitPolyProc; theProcs.rgnProc = gInitRgnProc; oldProcs = gGenericGWorld->grafProcs; gGenericGWorld->grafProcs = &theProcs; HLock((*theImage)->data); KeepSpinning(); if (gQTVersion) DrawTrimmedPicture((PicHandle)(*theImage)->data, &theRect, nil, false, nil); else DrawPicture((PicHandle)(*theImage)->data, &theRect); KeepSpinning(); HSetState((*theImage)->data, hState); gGenericGWorld->grafProcs = oldProcs; PopPort(); if (!(*theImage)->depth) (*theImage)->depth = 1; if (gHasObjects) (*theImage)->flags |= ifNeedsWhiteBG + ifNoOnscreenProg; (*theImage)->comments = gPICTComments; (*(PICTPrivatesHandle)(*theImage)->privateData)->totalLines = gTotalLines; } /* * SavePICTFile(theSpec, theHandle) * * Purpose: Writes the PICT image out to the specified file * Inputs: theSpec = a pointer to the output file spec * theHandle = the handle of the data to be written * Returns: an OSErr describing what went wrong * */ OSErr SavePICT(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle privates) { #if applec #pragma unused(thePreview, theRect, privates) #endif long theSize = GetHandleSize(theHandle); char hState = HGetState(theHandle); uchar *theHeader[kHeaderSize]; short theFile; OSErr theErr; long i; for (i = 0; i < kHeaderSize; theHeader[i++] = 0); KeepSpinning(); theErr = FSpCreate(theSpec, kCreator, kPICTType, 0); if (theErr == noErr) { KeepSpinning(); theErr = FSpOpenDF(theSpec, fsWrPerm, &theFile); if (theErr == noErr) { KeepSpinning(); theErr = FSWrite(theFile, &i, theHeader); if (theErr == noErr) { HLock(theHandle); SpinIndef(); theErr = FSWrite(theFile, &theSize, *theHandle); KeepSpinning(); if (theErr == noErr) { HSetState(theHandle, hState); FSClose(theFile); return theErr; } else gIntError = errCantWriteFile; HSetState(theHandle, hState); } else gIntError = errCantWriteFile; FSClose(theFile); } else gIntError = errCantOpenFile; FSpDelete(theSpec); } else gIntError = errCantCreateFile; return theErr; } /* * FixPICT(addPreview) * * Purpose: Performs the JFIF->PICT conversion on the active image, add the color * table, crops it, and creates a preview if requested * Inputs: addPreview = flag: true if we should add a preview image * theSize = pointer to a long where we will return the size * Returns: an OSErr describing what went wrong * */ OSErr FixPICT(ImageHandle theImage, Handle *finalData, Boolean palette) { OSErr theErr = noErr; Handle oldData; if ((*theImage)->format->inType != kPICTType && (*theImage)->format->inType != kSCRNType && (*theImage)->format->inType != kJPEGType) return errAETypeError; oldData = *finalData = (*theImage)->data; if ((*theImage)->format->inType == kJPEGType) { KeepSpinning(); *finalData = WrapJPEG(oldData, (*theImage)->depth); if ((*theImage)->data != oldData) DisposeHandle(oldData); if (!*finalData) return memFullErr; oldData = *finalData; } if (palette) { KeepSpinning(); *finalData = AddColors(oldData, theImage); if ((*theImage)->data != oldData) DisposeHandle(oldData); if (!*finalData) return gIntError = errNoColorsMemory, memFullErr; oldData = *finalData; } return theErr; } /* * AddColors(theHandle, theImage) * * Purpose: Adds the image's palette to the image description of the PICT * Inputs: theHandle = handle to the image data * theImage = handle to the associated image * Returns: a handle to the cropped image * */ Handle AddColors(Handle theHandle, ImageHandle theImage) { PixMapHandle thePixMap = GetGWorldPixMap(gGenericGWorld); CQDProcs theProcs, *oldProcs = gGenericGWorld->grafProcs; long theSize = GetHandleSize(theHandle); char hState = HGetState(theHandle); Rect theRect = (*theImage)->qrect; OpenCPicParams theParams; Handle dstHandle; OSErr theErr; if (!(*theImage)->qpalette) return theHandle; if (MakeMemAvailable(theSize + 16384L)) { theParams.srcRect = theRect; theParams.hRes = theParams.vRes = 0x480000L; theParams.version = -2; theParams.reserved1 = theParams.reserved2 = 0; SetStdCProcs(&theProcs); if (!gProgressPixProc) InitPICTUPPs(); theProcs.newProc1 = (UniversalProcPtr)gAddColorsPixProc; theProcs.bitsProc = gDummyBitsProc; theProcs.textProc = gDummyTextProc; theProcs.lineProc = gDummyLineProc; theProcs.rectProc = gDummyRectProc; theProcs.rRectProc = gDummyRRectProc; theProcs.ovalProc = gDummyOvalProc; theProcs.arcProc = gDummyArcProc; theProcs.polyProc = gDummyPolyProc; theProcs.rgnProc = gDummyRgnProc; gGenericGWorld->grafProcs = &theProcs; PushPort(); MySetPort(gGenericGWorld); ClipRect(&theParams.srcRect); if (dstHandle = (Handle)OpenCPicture(&theParams)) { LockPixels(thePixMap); HLock(theHandle); gPICTImage = theImage; KeepSpinning(); theErr = DrawTrimmedPicture((PicHandle)theHandle, &theParams.srcRect, nil, false, (ICMProgressProcRecordPtr)&gDummyProg); KeepSpinning(); HSetState(theHandle, hState); UnlockPixels(thePixMap); ClosePicture(); gGenericGWorld->grafProcs = oldProcs; if ((theErr == noErr) && !EmptyRect(&(*(PicHandle)dstHandle)->picFrame)) { PopPort(); return dstHandle; } DisposeHandle(dstHandle); } else theErr = memFullErr; gGenericGWorld->grafProcs = oldProcs; PopPort(); } else theErr = memFullErr; return nil; } /* * AddColorsPixProc(src, srcRect, matrix, mode, mask, matte, matteRect, callOldBits) * * Purpose: Dummy routine called when a compressed PixMap is found in a PICT; we just * add a color table to the ImageDescription * Inputs: src = the compressed PixMap * srcRect = the rectangle of the image in the source coordinates * matrix = the transformation matrix * mode = the drawing mode * mask = the output masking region * matte = the output matte, described as a PixMap * matteRect = the bounding rectangle for the output matte * callOldBits = flag saying if we should call the old routine * Returns: nothing * */ pascal void AddColorsPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short flags) { #if applec #pragma unused(flags) #endif PixMapHandle dst = GetGWorldPixMap((CGrafPtr)qd.thePort); ImageDescriptionHandle theDesc; ICMProgressProcRecord progProc; CTabHandle theColors = nil; ICMDataProcRecord dataProc; OSErr theError; long bufSize; Ptr theData; KeepSpinning(); if (GetCompressedPixMapInfo(src, &theDesc, &theData, &bufSize, &dataProc, &progProc) == noErr) { if (theColors = (CTabHandle)AnyNewHandle(sizeof(ColorTable))) { Palette2CTab((*gPICTImage)->qpalette, theColors); (*theColors)->ctSeed = GetCTSeed(); SetImageDescriptionCTable(theDesc, theColors); DisposeHandle((Handle)theColors); theError = SetCompressedPixMapInfo(src, theDesc, theData, bufSize, &dataProc, &progProc); } } StdPix(src, srcRect, matrix, mode, mask, matte, matteRect, 0); } //===================================================================================== // Dummy QuickDraw bottlenecks to filter out non-PixMaps within PICTs //===================================================================================== /* * InitPixProc(src, srcRect, matrix, mode, mask, matte, matteRect, callOldBits) * * Purpose: Dummy routine called when a compressed PixMap is found in a PICT; we just * copy the image description to a handle lPICTDesc * Inputs: src = the compressed PixMap * srcRect = the rectangle of the image in the source coordinates * matrix = the transformation matrix * mode = the drawing mode * mask = the output masking region * matte = the output matte, described as a PixMap * matteRect = the bounding rectangle for the output matte * callOldBits = flag saying if we should call the old routine * Returns: nothing * */ pascal void InitPixProc(PixMap *src, Rect *srcRect, MatrixRecord *matrix, short mode, RgnHandle mask, PixMap *matte, Rect *matteRect, short callOldBits) { #if applec #pragma unused(mode, mask, matte, matteRect, callOldBits) #endif ImageDescriptionHandle theDesc; ICMProgressProcRecord progProc; CTabHandle theColors = nil; ICMDataProcRecord dataProc; long bufSize; Ptr theData; gTotalLines += Height(srcRect); gPICTSrcRect = *srcRect; gPICTDstRect = *srcRect; TransformRect(matrix, &gPICTDstRect, nil); if (!GetCompressedPixMapInfo(src, &theDesc, &theData, &bufSize, &dataProc, &progProc)) { if ((*theDesc)->cType == kJPEGCompression) { if (!VerifyJPEGData((uchar *)theData, bufSize)) gIntError = errBadJPEG; ExtractComments(theData, bufSize, &gPICTComments); } BlockMove(*theDesc, &(*gPICTImage)->desc, sizeof(ImageDescription)); (*gPICTImage)->depth = (*theDesc)->depth; if ((*theDesc)->clutID != -1) { GetImageDescriptionCTable(theDesc, &theColors); if (theColors) { (*gPICTImage)->ipalette = NewPalette((*theColors)->ctSize + 1, theColors, pmTolerant, 0); DisposeHandle((Handle)theColors); } } } } /* * InitBitsProc(src, srcRect, dstRect, mode, mask) * * Purpose: Routine called in place of CopyBits for our images; here we check for a * custom color table * Inputs: src = the compressed PixMap * srcRect = the rectangle of the image in the source coordinates * dstRect = the destination rectangle * mode = the drawing mode * mask = the output masking region * Returns: nothing * */ pascal void InitBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask) { #if applec #pragma unused(srcRect, dstRect, mode, mask) #endif if (!(*gPICTImage)->depth) { if (src->rowBytes & 0x8000) { (*gPICTImage)->depth = src->pixelSize; if ((src->pixelSize <= 8) && src->pmTable) (*gPICTImage)->ipalette = NewPalette((*src->pmTable)->ctSize + 1, src->pmTable, pmTolerant, 0); } else (*gPICTImage)->depth = 1; } } pascal void InitTextProc(short count, const void *textAddr, Point numer, Point denom) { #if applec #pragma unused(count, textAddr, numer, denom) #endif gHasObjects = true; } pascal void InitLineProc(Point newPt) { #if applec #pragma unused(newPt) #endif gHasObjects = true; } pascal void InitRectProc(GrafVerb verb, const Rect *r) { #if applec #pragma unused(verb, r) #endif gHasObjects = true; } pascal void InitRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, short ovalHeight) { #if applec #pragma unused(verb, r, ovalWidth, ovalHeight) #endif gHasObjects = true; } pascal void InitOvalProc(GrafVerb verb, const Rect *r) { #if applec #pragma unused(verb, r) #endif gHasObjects = true; } pascal void InitArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle) { #if applec #pragma unused(verb, r, startAngle, arcAngle) #endif gHasObjects = true; } pascal void InitPolyProc(GrafVerb verb, PolyHandle poly) { #if applec #pragma unused(verb, poly) #endif gHasObjects = true; } pascal void InitRgnProc(GrafVerb verb, RgnHandle rgn) { #if applec #pragma unused(verb, rgn) #endif gHasObjects = true; } //===================================================================================== // Dummy QuickDraw bottlenecks to filter out non-PixMaps within PICTs //===================================================================================== pascal void DummyBitsProc(PixMap *src, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask) { #if applec #pragma unused(src, srcRect, dstRect, mode, mask) #endif } pascal void DummyTextProc(short count, const void *textAddr, Point numer, Point denom) { #if applec #pragma unused(count, textAddr, numer, denom) #endif } pascal void DummyLineProc(Point newPt) { #if applec #pragma unused(newPt) #endif } pascal void DummyRectProc(GrafVerb verb, const Rect *r) { #if applec #pragma unused(verb, r) #endif } pascal void DummyRRectProc(GrafVerb verb, const Rect *r, short ovalWidth, short ovalHeight) { #if applec #pragma unused(verb, r, ovalWidth, ovalHeight) #endif } pascal void DummyOvalProc(GrafVerb verb, const Rect *r) { #if applec #pragma unused(verb, r) #endif } pascal void DummyArcProc(GrafVerb verb, const Rect *r, short startAngle, short arcAngle) { #if applec #pragma unused(verb, r, startAngle, arcAngle) #endif } pascal void DummyPolyProc(GrafVerb verb, PolyHandle poly) { #if applec #pragma unused(verb, poly) #endif } pascal void DummyRgnProc(GrafVerb verb, RgnHandle rgn) { #if applec #pragma unused(verb, rgn) #endif } \ No newline at end of file diff --git a/Source/C/PNTG.c b/Source/C/PNTG.c new file mode 100644 index 0000000..8a2278a --- /dev/null +++ b/Source/C/PNTG.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "PNTG.h" //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr DecompressPNTGImage(uchar *dataStart, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length); static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow); //===================================================================================== // Boolean idPNTG(uchar *theData, long theSize) //===================================================================================== // Examines the given data and attempts to identify it as a PNTG image. //===================================================================================== extern Boolean idPNTG(uchar *theData, long theSize, short refNum, FSSpec *theSpec) { #if applec #pragma unused(theData, theSize, theSpec) #endif OSErr theErr; long size; theErr = GetEOF(refNum, &size); return (theErr == noErr && size <= (512 + 720 * 73)); } //===================================================================================== // OSErr OpenPNTG(ImageHandle theImage) //===================================================================================== // Initializes the image record for a PNTG image. //===================================================================================== extern OSErr OpenPNTG(ImageHandle theImage) { OSErr theErr = noErr; (*theImage)->grect.right = 576; (*theImage)->grect.bottom = 720; (*theImage)->depth = 1; (*theImage)->qrect = (*theImage)->crect = (*theImage)->grect; (*theImage)->compression = kPackBitsCompression; BlockMove(gString[strPackBits], (*theImage)->compressionDesc, *gString[strPackBits] + 1); return theErr; } //===================================================================================== // OSErr DrawPNTG(Handle theHandle, JVDrawParamsHandle theParams) //===================================================================================== // Draws a PNTG image into the specified GWorld, from the srcRect into the dstRect, // clipping as dstRgn specifies. //===================================================================================== extern OSErr DrawPNTG(Handle theHandle, JVDrawParamsHandle theParams) { NestedProgress theProgress = (*theParams)->progress; char hState = HGetState(theHandle); OSErr theErr = noErr; GWorldPtr theGWorld; uchar *dataStart; if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon); HLockHi(theHandle); if (theErr == noErr) { dataStart = (uchar *)StripAddress(*theHandle); theGWorld = NewTempGWorld(576, 720, 1, nil); if (theGWorld) { theErr = DecompressPNTGImage(dataStart, GetGWorldPixMap(theGWorld), (ICMProgressProcRecordPtr)&theProgress, GetHandleSize(theHandle)); if ((*theParams)->progress.aborted) theErr = codecAbortErr; DisposeGWorld(theGWorld); } else gIntError = errNoDrawMemory, theErr = memFullErr; } HSetState(theHandle, hState); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon); return theErr; } //===================================================================================== // OSErr DecompressPNTGImage(uchar *dataStart, PixMapHandle dstPixMap, // ICMProgressProcRecordPtr prog, Size length) //===================================================================================== // Oversees the decompression of a PNTG image, handling banding, and calling the // appropriate function to perform the actual decompression. //===================================================================================== static OSErr DecompressPNTGImage(uchar *dataStart, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length) { uchar *ptr, *rowStart, *dst, *dataEnd = dataStart + length; char pState = GetPixelsState(dstPixMap); RgnHandle dstRgn = qd.thePort->visRgn; ulong bandRow = 0, row; char mmuMode = true32b; OSErr theErr = noErr; LockPixels(dstPixMap); rowStart = (uchar *)GetPixBaseAddr(dstPixMap); ptr = dataStart + 512; for (row = 0; row < 720; row++) { if (ptr < dataStart || ptr > dataEnd) { theErr = codecBadDataErr; break; } SwapMMUMode(&mmuMode); dst = rowStart; UnpackBits((Ptr *)&ptr, (Ptr *)&dst, 576 / 8); SwapMMUMode(&mmuMode); rowStart += ((*dstPixMap)->rowBytes & 0x3fff); if (!(row & 63) && prog->progressProc) theErr = (OSErr)CallICMProgressProc(prog->progressProc, codecProgressUpdatePercent, FixRatio(row, 720), prog->progressRefCon); if (++bandRow == Height(&(*dstPixMap)->bounds)) { CopyPixMapToDestination(dstPixMap, row - bandRow + 1); bandRow = 0; rowStart = (uchar *)GetPixBaseAddr(dstPixMap); } if (theErr != noErr) break; } if (theErr == noErr && bandRow) CopyPixMapToDestination(dstPixMap, row - bandRow); SetPixelsState(dstPixMap, pState); return theErr; } //===================================================================================== // void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) //===================================================================================== // Copies the band contained in srcPixMap to the destination, offset from the top by // startRow. //===================================================================================== static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) { Rect srcRect = (*srcPixMap)->bounds, dstRect = (*srcPixMap)->bounds; PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); char srcState = HGetState((Handle)srcPixMap); char dstState = HGetState((Handle)dstPixMap); OffsetRect(&dstRect, 0, startRow); HLock((Handle)srcPixMap); HLock((Handle)dstPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &srcRect, &dstRect, srcCopy + ditherCopy, qd.thePort->visRgn); HSetState((Handle)dstPixMap, dstState); HSetState((Handle)srcPixMap, srcState); } \ No newline at end of file diff --git a/Source/C/PowerPCStub.c b/Source/C/PowerPCStub.c new file mode 100644 index 0000000..fd18495 --- /dev/null +++ b/Source/C/PowerPCStub.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #include #include #include #include #include #include main() { // initialize the Toolbox here InitGraf(&qd.thePort); InitFonts(); InitWindows(); InitMenus(); TEInit(); InitDialogs(nil); InitCursor(); StopAlert(9876, nil); } \ No newline at end of file diff --git a/Source/C/Preferences.c b/Source/C/Preferences.c new file mode 100644 index 0000000..012447b --- /dev/null +++ b/Source/C/Preferences.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local variables: * lPrefsDialog = preferences dialog pointer * */ static DialogPtr gPrefsDialog = nil; /* * OpenPrefs() * * Purpose: Opens the preferences dialog window * Inputs: initialSection = the starting menu item * Returns: nothing * */ OSErr OpenPrefs(void) { OSErr theErr = noErr; short i; if (gPrefsDialog) { if (!WindowVisible(gPrefsDialog)) FWShowWindow(gPrefsDialog); return noErr; } gOldPrefs = gThePrefs; if (!(gPrefsDialog = AllocateDialog())) return gIntError = errNoMemory, memFullErr; StartSpinning(); PushPort(); MySetPort(nil); if (gPrefsDialog = FWGetNewDialog(rPrefsDialog, (Ptr)gPrefsDialog, (WindowPtr)-1)) { for (i = prefsWindows; i <= prefsStartup; i++) { if (i != gThePrefs.prefsSection) HidePrefsItems(i); UpdatePrefsButtons(i); KeepSpinning(); } SetItemHandle(gPrefsDialog, prefsBoxUser, (Handle)gPopUpMenuBox); SetDCtlValue(gPrefsDialog, prefsPopUpMenu, gThePrefs.prefsSection); PlaceWindow(gPrefsDialog, &gThePrefs.prefsBounds, CenterWindow(gPrefsDialog)); } else gIntError = errNoMemory, theErr = memFullErr, DeallocateDialog(gPrefsDialog); StopSpinning(&qd.arrow); PopPort(); return theErr; } /* * ClosePrefs() * * Purpose: Closes the preferences dialog window * Inputs: initialSection = the starting menu item * Returns: nothing * */ void ClosePrefs(void) { PushPort(); MySetPort(nil); if (gPrefsDialog) { SaveWindowPosition(gPrefsDialog, &gThePrefs.prefsBounds); FWCloseDialog(gPrefsDialog); DisposeHandle(((DialogPeek)gPrefsDialog)->items); DeallocateDialog(gPrefsDialog); } gPrefsDialog = nil; PopPort(); ChangeActive(FWFrontWindow()); } /* * GetPrefsWindow() * * Purpose: Returns a pointer to the preferences dialog * Inputs: none * Returns: nothing * */ WindowPtr GetPrefsWindow(void) { return (WindowPtr)gPrefsDialog; } /* * HandlePrefsEvent(theDialog, theItem) * * Purpose: Makes changes to the preferences settings as indicated by theItem * Inputs: theDialog = pointer to the preferences dialog * theItem = the dialog item which was hit * Returns: true if the OK or Cancel buttons were hit; false otherwise * */ void HandlePrefsEvent(short theItem) { short i; switch (theItem) { case kDialogClose: SaveGeneralPrefs(); ClosePrefs(); return; case kDialogOK: case kDialogCancel: SaveGeneralPrefs(); SendCloseWindow(gPrefsDialog); return; case prefsPopUpMenu: gThePrefs.prefsSection = GetDCtlValue(gPrefsDialog, prefsPopUpMenu); for (i = prefsWindows; i <= prefsStartup; i++) if (i != gThePrefs.prefsSection) HidePrefsItems(i); ShowPrefsItems(gThePrefs.prefsSection); break; case prefsImageDeepestButton: gThePrefs.openScreen = osDeepest; break; case prefsImageLargestButton: gThePrefs.openScreen = osLargest; break; case prefsImageMainButton: gThePrefs.openScreen = osMain; break; case prefsUseColorBox: gThePrefs.pickColor = !gThePrefs.pickColor; break; case prefsAlwaysFullButton: gThePrefs.openFull = ofNoMatterWhat; break; case prefsAlwaysLargeButton: gThePrefs.openFull = ofAlways; break; case prefsAskLargeButton: gThePrefs.openFull = ofAsk; break; case prefsNeverFullButton: gThePrefs.openFull = ofNever; break; case prefsExpandSmallBox: gThePrefs.expandSmall = !gThePrefs.expandSmall;break; case prefsOnlyOneBox: gThePrefs.onlyOne = !gThePrefs.onlyOne; break; case prefsVHighQualityButton: gThePrefs.imageQuality = iqVHigh; break; case prefsHighQualityButton: gThePrefs.imageQuality = iqHigh; break; case prefsMedQualityButton: gThePrefs.imageQuality = iqMedium; break; case prefsBackgroundBox: gThePrefs.updateBack = !gThePrefs.updateBack;break; case prefsQuantizeAlwaysButton: gThePrefs.autoQuant = aqAlways; break; case prefsQuantizeOnlyButton: gThePrefs.autoQuant = aqOnly; break; case prefsQuantizeNeverButton: gThePrefs.autoQuant = aqNever; break; case prefsDitherQuantizedBox: gThePrefs.ditherQuant = !gThePrefs.ditherQuant; break; case prefsUsePaletteBox: gThePrefs.imagePalette = !gThePrefs.imagePalette; break; case prefsRestoreColorsBox: gThePrefs.restoreColors = !gThePrefs.restoreColors; break; case prefsBitmapsAlwaysButton: gThePrefs.useBitmaps = ubAlways; break; case prefsBitmapsOptionalButton:gThePrefs.useBitmaps = ubOptional; break; case prefsBitmapsNeverButton: gThePrefs.useBitmaps = ubNever; break; case prefsOriginalSizeBox: gThePrefs.origSize = !gThePrefs.origSize; break; case prefsNoUncompressedBox: gThePrefs.noUncomp = !gThePrefs.noUncomp; break; case prefsFixFilesBox: gThePrefs.autoFix = !gThePrefs.autoFix; break; case prefsFixCreatorsBox: gThePrefs.changeCreator = !gThePrefs.changeCreator;break; case prefsSaveQAlwaysButton: gThePrefs.saveQuant = sqAlways; break; case prefsSaveQOnlyButton: gThePrefs.saveQuant = sqOnly; break; case prefsSaveQNeverButton: gThePrefs.saveQuant = sqNever; break; case prefsDefaultPICTBox: gThePrefs.savePICT = !gThePrefs.savePICT; break; case prefsSavePreviewsBox: gThePrefs.savePrev = !gThePrefs.savePrev; break; case prefsCompressPreviewsBox: gThePrefs.compressPrev = !gThePrefs.compressPrev; break; case prefsAddIconsBox: gThePrefs.makeIcons = !gThePrefs.makeIcons; break; case prefsIconStyleMenu: gThePrefs.iconStyle = GetDCtlValue(gPrefsDialog, prefsIconStyleMenu); break; case prefsBeginSlidesButton: gThePrefs.startWith = swAutoSlide; break; case prefsSlideDialogButton: gThePrefs.startWith = swSlide; break; case prefsOpenDialogButton: gThePrefs.startWith = swOpen; break; case prefsNothingButton: gThePrefs.startWith = swNone; break; case prefsAutoCommentsBox: gThePrefs.autoComments = !gThePrefs.autoComments;break; case prefsMaximalBox: gThePrefs.backgroundTime = bgMaximal; break; case prefsReasonableBox: gThePrefs.backgroundTime = bgReasonable; break; case prefsMinimalBox: gThePrefs.backgroundTime = bgMinimal; break; case prefsUseQuickTimeBox: gThePrefs.useQuickTime = !gThePrefs.useQuickTime;break; } UpdatePrefsButtons(gThePrefs.prefsSection); } /* * HandlePrefsKey(theChar) * * Purpose: Handles key down events in the preferences dialog * Inputs: theChar = the ASCII representation of the character * Returns: nothing * */ Boolean HandlePrefsKey(char theChar) { if (theChar == kDownArrowChar && gThePrefs.prefsSection < prefsStartup) { SetDCtlValue(gPrefsDialog, prefsPopUpMenu, GetDCtlValue(gPrefsDialog, prefsPopUpMenu) + 1); HandlePrefsEvent(prefsPopUpMenu); } else if (theChar == kUpArrowChar && gThePrefs.prefsSection > prefsWindows) { SetDCtlValue(gPrefsDialog, prefsPopUpMenu, GetDCtlValue(gPrefsDialog, prefsPopUpMenu) - 1); HandlePrefsEvent(prefsPopUpMenu); } return true; } /* * HidePrefsItems(theSect) * * Purpose: Hides all the dialog items in theSect * Inputs: theSect = the section number of items to hide * Returns: nothing * */ void HidePrefsItems(short theSect) { short i; switch (theSect) { case prefsWindows: for (i = prefsFirstWindowsItem; i <= prefsLastWindowsItem; i++) HideDItem(gPrefsDialog, i); break; case prefsDisplay: for (i = prefsFirstDisplayItem; i <= prefsLastDisplayItem; i++) HideDItem(gPrefsDialog, i); break; case prefsOffscreen: for (i = prefsFirstBitmapsItem; i <= prefsLastBitmapsItem; i++) HideDItem(gPrefsDialog, i); break; case prefsFiles: for (i = prefsFirstFilesItem; i <= prefsLastFilesItem; i++) HideDItem(gPrefsDialog, i); break; case prefsStartup: for (i = prefsFirstMiscItem; i <= prefsLastMiscItem; i++) HideDItem(gPrefsDialog, i); break; } } /* * ShowPrefsItems(theSect) * * Purpose: Shows all the dialog items in theSect * Inputs: theSect = the section number of items to show * Returns: nothing * */ void ShowPrefsItems(short theSect) { short i; switch (theSect) { case prefsWindows: for (i = prefsFirstWindowsItem; i <= prefsLastWindowsItem; i++) ShowDItem(gPrefsDialog, i); break; case prefsDisplay: for (i = prefsFirstDisplayItem; i <= prefsLastDisplayItem; i++) ShowDItem(gPrefsDialog, i); break; case prefsOffscreen: for (i = prefsFirstBitmapsItem; i <= prefsLastBitmapsItem; i++) ShowDItem(gPrefsDialog, i); break; case prefsFiles: for (i = prefsFirstFilesItem; i <= prefsLastFilesItem; i++) ShowDItem(gPrefsDialog, i); break; case prefsStartup: for (i = prefsFirstMiscItem; i <= prefsLastMiscItem; i++) ShowDItem(gPrefsDialog, i); break; } } /* * UpdatePrefsButtons(theSect) * * Purpose: Updates the values of all the buttons in the given section of the * preferences dialog * Inputs: theSect = the section number we want to update * Returns: nothing * */ void UpdatePrefsButtons(short theSect) { switch (theSect) { case prefsWindows: SetDCtlValue(gPrefsDialog, prefsImageDeepestButton, gThePrefs.openScreen == osDeepest); SetDCtlValue(gPrefsDialog, prefsImageLargestButton, gThePrefs.openScreen == osLargest); SetDCtlValue(gPrefsDialog, prefsImageMainButton, gThePrefs.openScreen == osMain); SetDCtlValue(gPrefsDialog, prefsUseColorBox, gThePrefs.pickColor); SetDCtlValue(gPrefsDialog, prefsAlwaysFullButton, gThePrefs.openFull == ofNoMatterWhat); SetDCtlValue(gPrefsDialog, prefsAlwaysLargeButton, gThePrefs.openFull == ofAlways); SetDCtlValue(gPrefsDialog, prefsAskLargeButton, gThePrefs.openFull == ofAsk); SetDCtlValue(gPrefsDialog, prefsNeverFullButton, gThePrefs.openFull == ofNever); SetDCtlValue(gPrefsDialog, prefsExpandSmallBox, gThePrefs.expandSmall); SetDCtlValue(gPrefsDialog, prefsOnlyOneBox, gThePrefs.onlyOne); break; case prefsDisplay: SetDCtlValue(gPrefsDialog, prefsVHighQualityButton, gThePrefs.imageQuality == iqVHigh); SetDCtlValue(gPrefsDialog, prefsHighQualityButton, gThePrefs.imageQuality == iqHigh); SetDCtlValue(gPrefsDialog, prefsMedQualityButton, gThePrefs.imageQuality == iqMedium); SetDCtlValue(gPrefsDialog, prefsBackgroundBox, !gThePrefs.updateBack); SetDCtlValue(gPrefsDialog, prefsQuantizeAlwaysButton, gThePrefs.autoQuant == aqAlways); SetDCtlValue(gPrefsDialog, prefsQuantizeOnlyButton, gThePrefs.autoQuant == aqOnly); SetDCtlValue(gPrefsDialog, prefsQuantizeNeverButton, gThePrefs.autoQuant == aqNever); SetDCtlValue(gPrefsDialog, prefsDitherQuantizedBox, gThePrefs.ditherQuant); SetDCtlValue(gPrefsDialog, prefsUsePaletteBox, gThePrefs.imagePalette); SetDCtlValue(gPrefsDialog, prefsRestoreColorsBox, gThePrefs.restoreColors); break; case prefsOffscreen: SetDCtlValue(gPrefsDialog, prefsBitmapsAlwaysButton, gThePrefs.useBitmaps == ubAlways); SetDCtlValue(gPrefsDialog, prefsBitmapsOptionalButton, gThePrefs.useBitmaps == ubOptional); SetDCtlValue(gPrefsDialog, prefsBitmapsNeverButton, gThePrefs.useBitmaps == ubNever); SetDCtlValue(gPrefsDialog, prefsOriginalSizeBox, gThePrefs.origSize); SetDCtlValue(gPrefsDialog, prefsNoUncompressedBox, gThePrefs.noUncomp); break; case prefsFiles: SetDCtlValue(gPrefsDialog, prefsFixFilesBox, gThePrefs.autoFix); SetDCtlValue(gPrefsDialog, prefsFixCreatorsBox, gThePrefs.changeCreator); SetDCtlValue(gPrefsDialog, prefsSaveQAlwaysButton, gThePrefs.saveQuant == sqAlways); SetDCtlValue(gPrefsDialog, prefsSaveQOnlyButton, gThePrefs.saveQuant == sqOnly); SetDCtlValue(gPrefsDialog, prefsSaveQNeverButton, gThePrefs.saveQuant == sqNever); SetDCtlValue(gPrefsDialog, prefsDefaultPICTBox, gThePrefs.savePICT); SetDCtlValue(gPrefsDialog, prefsSavePreviewsBox, gThePrefs.savePrev); SetDCtlValue(gPrefsDialog, prefsCompressPreviewsBox, gThePrefs.compressPrev); SetDCtlValue(gPrefsDialog, prefsAddIconsBox, gThePrefs.makeIcons); SetDCtlValue(gPrefsDialog, prefsIconStyleMenu, gThePrefs.iconStyle); break; case prefsStartup: SetDCtlValue(gPrefsDialog, prefsBeginSlidesButton, gThePrefs.startWith == swAutoSlide); SetDCtlValue(gPrefsDialog, prefsSlideDialogButton, gThePrefs.startWith == swSlide); SetDCtlValue(gPrefsDialog, prefsOpenDialogButton, gThePrefs.startWith == swOpen); SetDCtlValue(gPrefsDialog, prefsNothingButton, gThePrefs.startWith == swNone); SetDCtlValue(gPrefsDialog, prefsAutoCommentsBox, gThePrefs.autoComments); SetDCtlValue(gPrefsDialog, prefsMaximalBox, gThePrefs.backgroundTime == bgMaximal); SetDCtlValue(gPrefsDialog, prefsReasonableBox, gThePrefs.backgroundTime == bgReasonable); SetDCtlValue(gPrefsDialog, prefsMinimalBox, gThePrefs.backgroundTime == bgMinimal); SetDCtlValue(gPrefsDialog, prefsUseQuickTimeBox, gThePrefs.useQuickTime); break; } } /* * GetPrefsSpec(theSpec) * * Purpose: Locates the preferences folder and returns an FSSpec pointing to the * JPEGView preferences file * Inputs: theSpec = pointer to a destination file specification * Returns: true if things went okay; false otherwise * */ Boolean GetPrefsSpec(FSSpec *theSpec) { short vRefNum; long dirID; if (FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &vRefNum, &dirID) == noErr) { FSMakeFSSpec(vRefNum, dirID, gString[strJPEGViewPrefs], theSpec); return true; } return false; } /* * SavePrefs() * * Purpose: Saves the current preferences into the preferences file * Inputs: none * Returns: nothing * */ extern void SaveGeneralPrefs(void) { long theSize = sizeof(gThePrefs); FSSpec theSpec; short theFile; OSErr theErr; if (GetPrefsSpec(&theSpec)) { theErr = FSpOpenDF(&theSpec, fsRdWrPerm, &theFile); if (theErr != noErr) { if ((theErr = FSpCreate(&theSpec, kCreator, kPrefsType, 0)) == noErr) theErr = FSpOpenDF(&theSpec, fsRdWrPerm, &theFile); } if (theErr == noErr) { if (SetEOF(theFile, 0L) == noErr) { if (FSWrite(theFile, &theSize, &gThePrefs) == noErr) { FSClose(theFile); return; } else MinorError(errCantWritePrefs); FSClose(theFile); } else MinorError(errCantWritePrefs); FSpDelete(&theSpec); } else MinorError(errCantWritePrefs); } else MinorError(errCantWritePrefs); } /* * LoadPrefs() * * Purpose: Loads the current preferences from the preferences file; if the file * isn't found, we write a new one with the default preferences; * if the preferences are from an old version, we display the help * beginning at the appropraite place * Inputs: none * Returns: nothing * */ extern void LoadGeneralPrefs(void) { long theSize = 0, start = 0; PrefsData thePrefs = gThePrefs; FSSpec theSpec; short theFile; if (GetPrefsSpec(&theSpec)) { if (FSpOpenDF(&theSpec, fsRdPerm, &theFile) == noErr) { theSize = sizeof(PrefsData); if (FSRead(theFile, &theSize, &thePrefs) == noErr) { if (thePrefs.versionID == kPrefsVersion && thePrefs.prefsSize == sizeof(PrefsData)) { gThePrefs = thePrefs; FSClose(theFile); return; } } FSClose(theFile); FSpDelete(&theSpec); } if (OpenHelp() == noErr) ChangeActive(GetHelpWindow()); } SaveGeneralPrefs(); } extern OSErr LoadPrefsHandle(OSType type, short index, Handle *theHandle) { OSErr theErr = noErr; FSSpec theSpec; short theFile; if (GetPrefsSpec(&theSpec)) { if ((theFile = FSpOpenResFile(&theSpec, fsRdPerm)) != -1) { if (*theHandle = Get1Resource(type, index)) { DetachResource(*theHandle); CloseResFile(theFile); return noErr; } else theErr = fnfErr; // need to signal something since ResError() == 0 CloseResFile(theFile); } else theErr = ResError(); } return theErr; } extern OSErr SavePrefsHandle(OSType type, short index, Handle theHandle) { OSErr theErr = noErr; Handle oldResource; FSSpec theSpec; short theFile; if (GetPrefsSpec(&theSpec)) { FSpCreateResFile(&theSpec, kCreator, kPrefsType, 0); if ((theFile = FSpOpenResFile(&theSpec, fsRdWrPerm)) != -1) { if (oldResource = Get1Resource(type, index)) { RmveResource(oldResource); if ((theErr = ResError()) == noErr) { DisposeHandle(oldResource); UpdateResFile(theFile); } else ReleaseResource(oldResource); } if (theErr == noErr) { AddResource(theHandle, type, index, (StringPtr)"\p"); if ((theErr = ResError()) == noErr) { WriteResource(theHandle); if ((theErr = ResError()) == noErr) { DetachResource(theHandle); UpdateResFile(theFile); CloseResFile(theFile); return noErr; } ReleaseResource(theHandle); } } CloseResFile(theFile); } else theErr = ResError(); } return theErr; } \ No newline at end of file diff --git a/Source/C/ProgressProcs.c b/Source/C/ProgressProcs.c new file mode 100644 index 0000000..e5e4581 --- /dev/null +++ b/Source/C/ProgressProcs.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "ProgressProcs.h" //===================================================================================== // Global variables local to this module //===================================================================================== static UserItemUPP gUpdateBar = nil, gUpdateBarIndef; static Fixed gProgressPercent; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static pascal void UpdateBar(DialogPtr theDialog, short theItem); static pascal void UpdateBarIndef(DialogPtr theDialog, short theItem); static void InitDrawProgress(Point *thePoint, JVDrawParamsHandle theParams); static void MakeDrawProgressText(short theMessage, StringPtr theNum, Fixed thePercent); //===================================================================================== // pascal OSErr DummyProgress(short theMessage, Fixed thePercent, long refCon) //===================================================================================== // Dummy progress proc; goes through all the motions, but is just used to make sure we // give up time to other applications while providing no real feedback to the user. //===================================================================================== extern pascal OSErr DummyProgress(short theMessage, Fixed thePercent, long refCon) { #if applec #pragma unused(thePercent) #endif NestedProgressPtr theProgress = nil; JVDrawParamsHandle theParams = nil; OSErr theErr = noErr; char hState; // figure out of we've got a handle to drawing parameters, or just a pointer // to a progress proc as the parameter; if we have a handle, lock it and // extract the pointer to the progress proc if (((NestedProgressPtr)refCon)->prog.progressProc == gDummyProg.prog.progressProc) theProgress = (NestedProgressPtr)refCon; else { theParams = (JVDrawParamsHandle)refCon; hState = HGetState((Handle)theParams); HLock((Handle)theParams); theProgress = &(*theParams)->progress; } // keep the cursor spinning, and track the various nesting levels as necessary // when open and close messages are received KeepSpinning(); switch (theMessage) { case codecProgressOpen: if (++theProgress->level <= 1) { theProgress->aborted = false; } break; case codecProgressClose: if (--theProgress->level > 0) break; break; } // check for aborts if (theProgress->aborted || (theProgress->aborted = CheckAbort(theParams))) theErr = codecAbortErr; // restore the drawing parameters handle to its original state and exit if (theParams) HSetState((Handle)theParams, hState); return theErr; } //===================================================================================== // pascal OSErr GenericProgress(short theMessage, Fixed thePercent, long refCon) //===================================================================================== // Generic progress procedure, which displays a dialog with a progress bar and a cancel // button. When calling with the open message, the thePercent parameter specifies // special options. If thePercent equals kModalProgress, then the dialog displayed is // a modal dialog, centered on the screen, rather than the usual movable modal. If // thePercent is set to kIndefProgress, then the percentage parameter is ignored in the // future, and the famous Finder "barber shop" progress bar is displayed instead. This // function can be called as often as desired; the display is never updated more than // 3 times/second. //===================================================================================== extern pascal OSErr GenericProgress(short theMessage, Fixed thePercent, long refCon) { static DialogPtr gTheDialog = nil; static long gLastTime; NestedProgressPtr theProgress = nil; JVDrawParamsHandle theParams = nil; OSErr theErr = noErr; char hState; long ticks; // figure out of we've got a handle to drawing parameters, or just a pointer // to a progress proc as the parameter; if we have a handle, lock it and // extract the pointer to the progress proc if (((NestedProgressPtr)refCon)->prog.progressProc == gGenericProgress) theProgress = (NestedProgressPtr)refCon; else { theParams = (JVDrawParamsHandle)refCon; hState = HGetState((Handle)theParams); HLock((Handle)theParams); theProgress = &(*theParams)->progress; } // save the port now, and calculate the scaled percentage KeepSpinning(); PushPort(); switch (theMessage) { case codecProgressOpen: // open the dialog if this is the first call if (++theProgress->level <= 1) { theProgress->aborted = false; MySetPort(nil); if (!(gTheDialog = AllocateDialog())) break; // we use the modal dialog if thePercent is set to kModalProgress if (gTheDialog = FWGetNewDialog((long)thePercent == kModalProgress ? rModalProgressDialog : rProgressDialog, nil, (WindowPtr)-1)) { MySetPort((CGrafPtr)gTheDialog); // set up the user item handler, either for indefinite progress // (thePercent == kIndefProgress) or for standard progress if (!gUpdateBar) { gUpdateBar = NewUserItemProc((ProcPtr)UpdateBar); gUpdateBarIndef = NewUserItemProc((ProcPtr)UpdateBarIndef); } SetItemHandle(gTheDialog, progressUser, (long)thePercent == kIndefProgress ? (Handle)gUpdateBarIndef : (Handle)gUpdateBar); gProgressPercent = 0L; PlaceWindow(gTheDialog, &gThePrefs.progressBounds, CenterWindow(gTheDialog)); HiliteMenu(0); MySetPort(nil); ShowWindow(gTheDialog); DrawDialog(gTheDialog); AdjustMenus(); } else DeallocateDialog(gTheDialog), gTheDialog = nil; } // reset the last time so that we draw right away, and update the initial // percentage gLastTime = 0; theErr = GenericProgress(codecProgressUpdatePercent, 0, refCon); break; case codecProgressUpdatePercent: if (gTheDialog) { // update our user item no more than 3x a second; do this by setting the // gProgressPercent global, and forcing an update of the bar userItem if ((TickCount() - gLastTime) < 10L) break; gLastTime = TickCount(); // scale the displayed percentage according to begin/end gProgressPercent = theProgress->begin + FixMul(thePercent, theProgress->end - theProgress->begin); UpdateDialogItem(gTheDialog, progressUser); } break; case codecProgressClose: // display the final percentage and delay for an instant GenericProgress(codecProgressUpdatePercent, 0x10000, refCon); Delay(1, &ticks); if (--theProgress->level > 0) break; // if this is the final nested call, save the position and exit MySetPort(nil); if (gTheDialog) { if (GetWVariant(gTheDialog) != dBoxProc) SaveWindowPosition(gTheDialog, &gThePrefs.progressBounds); if (gInBackground) FWHideFloatingWindows(); FWCloseDialog(gTheDialog); DisposeHandle(((DialogPeek)gTheDialog)->items); DeallocateDialog(gTheDialog); } gTheDialog = nil; break; } // restore the original port and check for aborts PopPort(); if (theErr == noErr) { if (theProgress->aborted || (theProgress->aborted = CheckAbort(theParams))) theErr = codecAbortErr; } // if there was an abort signalled, and the dialog is visible, hide it immediately // to give better user feedback if (theErr == codecAbortErr && gTheDialog && WindowVisible(gTheDialog)) FWHideWindow(gTheDialog); // restore the drawing parameters handle to its original state and exit if (theParams) HSetState((Handle)theParams, hState); return theErr; } //===================================================================================== // pascal void UpdateBar(DialogPtr theDialog, short theItem) //===================================================================================== // Draws the progress bar for the generic progress dialog, according to the percentage // stored in the global gProgressPercent. //===================================================================================== static pascal void UpdateBar(DialogPtr theDialog, short theItem) { static RGBColor gBarBackground = { 0xcccc, 0xcccc, 0xffff }; static RGBColor gBarForeground = { 0x4000, 0x4000, 0x4000 }; Boolean useBW = ((CGrafPtr)theDialog)->portPixMap && (*((CGrafPtr)theDialog)->portPixMap)->pixelSize == 1; Rect itemRect, leftRect, rightRect; Handle itemHandle; Fixed thePercent; short itemType; PushPort(); MySetPort((CGrafPtr)theDialog); thePercent = gProgressPercent; GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); PenSize(1, 1); RGBForeColor(&gBlack); FrameRect(&itemRect); InsetRect(&itemRect, 1, 1); rightRect = leftRect = itemRect; leftRect.right = itemRect.left + FixRound(FixMul(thePercent, Long2Fix(Width(&itemRect)))); rightRect.left = leftRect.right; if (leftRect.right > leftRect.left) { RGBForeColor(&gBarForeground); PaintRect(&leftRect); } if (rightRect.left < rightRect.right) { if (useBW) RGBForeColor(&gWhite); else RGBForeColor(&gBarBackground); PaintRect(&rightRect); } RGBForeColor(&gBlack); PopPort(); } //===================================================================================== // pascal void UpdateBarIndef(DialogPtr theDialog, short theItem) //===================================================================================== // Draws the progress bar for the generic progress dialog, in the Finder's "barber // shop" style. Used for progress display when the final count of things to be done is // not initially known. //===================================================================================== static pascal void UpdateBarIndef(DialogPtr theDialog, short theItem) { static RGBColor gBarBackground = { 0xcccc, 0xcccc, 0xffff }; static RGBColor gBarForeground = { 0x4000, 0x4000, 0x4000 }; static short gBarOffset = 0; Boolean useBW = ((CGrafPtr)theDialog)->portPixMap && (*((CGrafPtr)theDialog)->portPixMap)->pixelSize == 1; short itemType, left; Handle itemHandle; RgnHandle oldClip; Rect itemRect; if (!theDialog) return; PushPort(); MySetPort((CGrafPtr)theDialog); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); if (oldClip = NewRgn()) { GetClip(oldClip); PenSize(1, 1); RGBForeColor(&gBlack); FrameRect(&itemRect); InsetRect(&itemRect, 1, 1); ClipRect(&itemRect); left = itemRect.left - (3 * Height(&itemRect)) + (gBarOffset * Height(&itemRect) / 2); PenSize(Height(&itemRect), 1); while (left < itemRect.right) { RGBForeColor(&gBarForeground); MoveTo(left, itemRect.top); LineTo(left += Height(&itemRect), itemRect.bottom); if (useBW) RGBForeColor(&gWhite); else RGBForeColor(&gBarBackground); MoveTo(left, itemRect.top); LineTo(left += Height(&itemRect), itemRect.bottom); } PenSize(1, 1); SetClip(oldClip); DisposeRgn(oldClip); gBarOffset = (gBarOffset + 1) & 3; } RGBForeColor(&gBlack); PopPort(); } //===================================================================================== // pascal OSErr DrawProgress(short theMessage, Fixed thePercent, // JVDrawParamsHandle theParams) //===================================================================================== // Handles progress that is displayed during onscreen drawing. This is shown as a // small percentage in the bottom-right corner of the screen. There is a lot that we // need to be concerned with here, especially the possibility of overwriting an area // that has already been drawn, and calculating the best place to put the percentage. //===================================================================================== extern pascal OSErr DrawProgress(short theMessage, Fixed thePercent, JVDrawParamsHandle theParams) { static Fixed gLastPercent; static Point gThePoint; static long gLastTime; static short gLastH; Boolean state = (thePercent != 0); OSErr theErr = noErr; RgnHandle tempRgn; FontInfo theFont; Str255 theNum; Rect theRect; short i; // if we're not drawing onscreen, don't do this at all; otherwise, set port to the // onscreen port and go for it if (!(*theParams)->on.port) return noErr; KeepSpinning(); PushPort(); MySetPort((*theParams)->on.port); // calculate the scaled percentage, according to the nested progress we use thePercent = (*theParams)->progress.begin + FixMul(thePercent, (*theParams)->progress.end - (*theParams)->progress.begin); switch (theMessage) { case codecProgressOpen: // if this is the first nesting level, set the gDrawing flag, readjust the // menus, and calculate the best place to draw the progress percentage if (++(*theParams)->progress.level > 1) break; if (!gDrawing) gDrawing = (ImageHandle)-1; HiliteMenu(0); AdjustMenus(); InitDrawProgress(&gThePoint, theParams); (*theParams)->progress.aborted = false; GetFontInfo(&theFont); (*theParams)->endprogress = gThePoint.v - theFont.ascent - 2; gLastTime = 0; gLastH = 0; DrawProgress(codecProgressUpdatePercent, 0L, theParams); break; // if we get scaling or dithering messages, we use the last percentage case codecProgressUpdateScaling: case codecProgressUpdateDithering: thePercent = gLastPercent; case codecProgressUpdatePercent: gLastPercent = thePercent; // if we haven't drawn over the area where the progress is, we check to be // sure there's been at least 1/3 sec. since the last update; of course, this // doesn't apply if we've received the UpdateScaling or UpdateDithering msgs. if (!(*theParams)->endprogress || ((TickCount() - gLastTime) < 10L && theMessage == codecProgressUpdatePercent)) break; gLastTime = TickCount(); // here's where we actually determine the string and draw it onscreen SetClip(qd.thePort->visRgn); RGBForeColor(&gBlack); RGBBackColor(&gWhite); MakeDrawProgressText(state ? theMessage : codecProgressUpdatePercent, theNum, thePercent); i = gThePoint.h - StringWidth(theNum); MoveTo(i, gThePoint.v - 2); DrawString(theNum); MySetRect(&theRect, gLastH ? gLastH : i - 1, (*theParams)->endprogress, i, (*theParams)->drawProgressRect.bottom); PaintRect(&theRect); gLastH = i; break; case codecProgressClose: // if this isn't the last nesting level, just ignore for now if (--(*theParams)->progress.level > 0) break; gDrawing = nil; AdjustMenus(); // if we never drew over the area where the progress is, make sure we erase // it; otherwise it'll look funny if (!(*theParams)->endprogress) break; if (tempRgn = NewRgn()) { GetClip(tempRgn); SetClip((*theParams)->newupdates); MySetRect(&theRect, gLastH ? gLastH : (*theParams)->drawProgressRect.left, (*theParams)->endprogress, (*theParams)->drawProgressRect.right, (*theParams)->drawProgressRect.bottom); PaintRect(&theRect); SetClip(tempRgn); DisposeRgn(tempRgn); } break; } PopPort(); // restore the original port and check for aborts if ((*theParams)->progress.aborted || ((*theParams)->progress.aborted = CheckAbort(theParams))) theErr = codecAbortErr; return theErr; } //===================================================================================== // void InitProgress(Point *thePoint) //===================================================================================== // Handles progress that is displayed during onscreen drawing. This is shown as a // small percentage in the bottom-right corner of the screen. There is a lot that we // need to be concerned with here, especially the possibility of overwriting an area // that has already been drawn, and calculating the best place to put the percentage. //===================================================================================== static void InitDrawProgress(Point *thePoint, JVDrawParamsHandle theParams) { RgnHandle theRgn, textRgn; short height, width; FontInfo theFont; Str255 tempStr; Rect fullRect; PenNormal(); TextFont(geneva); TextMode(notSrcCopy); TextSize(9); BlockMove(gString[strDecompressing], tempStr, gString[strDecompressing][0] + 1); GetFontInfo(&theFont); height = theFont.leading + theFont.ascent + theFont.descent; width = StringWidth(tempStr); fullRect = (*theParams)->drawProgressRect; fullRect.bottom = (*qd.thePort->visRgn)->rgnBBox.bottom; if (fullRect.bottom > (*theParams)->drawProgressRect.bottom) fullRect.bottom = (*theParams)->drawProgressRect.bottom; MySetPt(thePoint, fullRect.right, fullRect.bottom); if (theRgn = NewRgn()) { if (textRgn = NewRgn()) { while (true) { while (true) { SetRectRgn(theRgn, fullRect.left, fullRect.bottom - 1, fullRect.right, fullRect.bottom); SectRgn(theRgn, qd.thePort->visRgn, theRgn); SetRectRgn(textRgn, (*theRgn)->rgnBBox.right - width, (*theRgn)->rgnBBox.bottom - height, (*theRgn)->rgnBBox.right, (*theRgn)->rgnBBox.bottom); SectRgn(textRgn, qd.thePort->visRgn, theRgn); if (EqualRgn(textRgn, theRgn)) break; if (EmptyRgn(theRgn)) break; fullRect.right = (*theRgn)->rgnBBox.right - 1; if (Width(&fullRect) < width) { fullRect.right = (*theParams)->drawProgressRect.right; break; } } if (EqualRgn(textRgn, theRgn)) break; fullRect.bottom -= 4; if (Height(&fullRect) < (height << 2)) { fullRect = (*theParams)->drawProgressRect; break; } } MySetPt(thePoint, (*theRgn)->rgnBBox.right - 1, (*theRgn)->rgnBBox.bottom); DisposeRgn(textRgn); } DisposeRgn(theRgn); } } //===================================================================================== // void MakeProgressText(short theMessage, StringPtr theNum, Fixed thePercent) //===================================================================================== // Assemble the string to display for the drawing progress. //===================================================================================== static void MakeDrawProgressText(short theMessage, StringPtr theNum, Fixed thePercent) { theNum[0] = 0; if (theMessage == codecProgressUpdateScaling && thePercent) AddString(theNum, gString[strScaling]); else if (theMessage == codecProgressUpdateDithering && thePercent) AddString(theNum, gString[strDithering]); else AddString(theNum, gString[strDecompressing]); StuffNumber(theNum, 1, FixRound(FixMul(thePercent, Long2Fix(100L)))); } //===================================================================================== // pascal OSErr SlideProgress(short theMessage, Fixed thePercent, long refCon) //===================================================================================== // Progress function for slide shows; draws a rotating little 2x1 dot in the // upper-right corner of the screen. //===================================================================================== extern pascal OSErr SlideProgress(short theMessage, Fixed thePercent, long refCon) { #if applec #pragma unused(thePercent) #endif static long gLastTime, gLastPos; JVDrawParamsHandle theParams = (JVDrawParamsHandle)refCon; ImageHandle theImage = FrontImage(); WindowPtr theWindow; Rect theRect; theWindow = (theImage && Full(theImage)) ? (*theImage)->window : GetSlideBackWindow(); KeepSpinning(); if (theWindow) { theRect = gImageRoot ? (*(*gImageRoot)->dmon)->rect : theWindow->portRect; PushPort(); MySetPort((CGrafPtr)theWindow); ClipRect(&theRect); switch (theMessage) { case codecProgressRealOpen: gLastTime = gLastPos = 0; SetCPixel(theRect.right - 1, theRect.top + 0, &gWhite); SetCPixel(theRect.right - 2, theRect.top + 0, &gWhite); SetCPixel(theRect.right - 1, theRect.top + 1, &gBlack); SetCPixel(theRect.right - 2, theRect.top + 1, &gBlack); break; case codecProgressUpdatePercent: if ((TickCount() - gLastTime) < 20L) break; gLastTime = TickCount(); switch (gLastPos = (gLastPos + 1) & 3) { case 0: SetCPixel(theRect.right - 2, theRect.top + 1, &gBlack); SetCPixel(theRect.right - 1, theRect.top + 0, &gWhite); break; case 1: SetCPixel(theRect.right - 2, theRect.top + 0, &gBlack); SetCPixel(theRect.right - 1, theRect.top + 1, &gWhite); break; case 2: SetCPixel(theRect.right - 1, theRect.top + 0, &gBlack); SetCPixel(theRect.right - 2, theRect.top + 1, &gWhite); break; case 3: SetCPixel(theRect.right - 1, theRect.top + 1, &gBlack); SetCPixel(theRect.right - 2, theRect.top + 0, &gWhite); break; } break; case codecProgressRealClose: SetCPixel(theRect.right - 1, theRect.top + 0, &gBlack); SetCPixel(theRect.right - 2, theRect.top + 0, &gBlack); SetCPixel(theRect.right - 1, theRect.top + 1, &gBlack); SetCPixel(theRect.right - 2, theRect.top + 1, &gBlack); break; } PopPort(); } if (theParams && ((*theParams)->progress.aborted || ((*theParams)->progress.aborted = CheckAbort(theParams)))) return codecAbortErr; else return noErr; } \ No newline at end of file diff --git a/Source/C/QDxDispatchPatch.c b/Source/C/QDxDispatchPatch.c new file mode 100644 index 0000000..5b65b64 --- /dev/null +++ b/Source/C/QDxDispatchPatch.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "QDxDispatchPatch.h" //===================================================================================== // Constants local to this module //===================================================================================== #define _QDxDispatch 0xAB1D //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static Boolean CheckForQuickTimeVM(void); //===================================================================================== // Global variables local to this module //===================================================================================== static ushort *gOnOffSwitch = nil; static ushort *gRoundGWorld = nil; static ulong *gOldTrapAddress = nil; static UniversalProcPtr gNewTrapAddress; //===================================================================================== // void InstallQDxDispatchPatch(void) //===================================================================================== // Installs a head patch to the _QDxDispatch trap that prevents any attempts at // allocating more than a 64k GWorld in temporary memory to fail. //===================================================================================== extern void InstallQDxDispatchPatch(Boolean roundGWorld) { static Boolean gFirstTime = true; if (!HasVirtualMemory()) return; if (gFirstTime) { Handle theHandle; gFirstTime = false; if (CheckForQuickTimeVM()) return; if (!(theHandle = GetResource(kPatchType, rQDxDispatchPatch))) return; DetachResource(theHandle); HLockHi(theHandle); HNoPurge(theHandle); gOnOffSwitch = (ushort *)StripAddress(*theHandle); gRoundGWorld = (ushort *)(gOnOffSwitch + 1); gOldTrapAddress = (ulong *)(gRoundGWorld + 1); gNewTrapAddress = (UniversalProcPtr)(gOldTrapAddress + 1); *gOldTrapAddress = (long)NGetTrapAddress(_QDxDispatch, ToolTrap); NSetTrapAddress(gNewTrapAddress, _QDxDispatch, ToolTrap); gMemSlop *= 2; } if (gOnOffSwitch) { *gOnOffSwitch = -1; *gRoundGWorld = roundGWorld; } } //===================================================================================== // void RemoveQDxDispatchPatch(void) //===================================================================================== // Sets the on/off switch on our patched trap. //===================================================================================== extern void RemoveQDxDispatchPatch(void) { if (gOnOffSwitch) *gOnOffSwitch = 0; } //===================================================================================== // Boolean GetQDxDispatchPatchState(void) //===================================================================================== // Returns the on/off setting of our patched trap. //===================================================================================== extern Boolean GetQDxDispatchPatchState(void) { if (gOnOffSwitch) return (*gOnOffSwitch != 0); return false; } //===================================================================================== // void SetQDxDispatchPatchState(Boolean on) //===================================================================================== // Sets the on/off setting of our patched trap. //===================================================================================== extern void SetQDxDispatchPatchState(Boolean on) { if (gOnOffSwitch) *gOnOffSwitch = (on) ? -1 : 0; } //===================================================================================== // void CheckForQuickTimeVM(void) //===================================================================================== // Scan the Extensions folder for a copy of the old QuickTime VM extension, and delete // any copies found there, alerting the user. If we're in the background, however, we // don't do anything, since it's not such a great time to post a notification. //===================================================================================== static Boolean CheckForQuickTimeVM(void) { CInfoPBRec block; Str255 fileName; //FSSpec theSpec; short vRefNum; long dirID; if (FindFolder(kOnSystemDisk, kExtensionFolderType, kDontCreateFolder, &vRefNum, &dirID) == noErr) { block.hFileInfo.ioNamePtr = fileName; block.hFileInfo.ioFDirIndex = 1; block.hFileInfo.ioVRefNum = vRefNum; block.hFileInfo.ioDirID = dirID; while (PBGetCatInfo(&block, false) == noErr) { if (block.hFileInfo.ioFlFndrInfo.fdType == 'INIT' && block.hFileInfo.ioFlFndrInfo.fdCreator == 'QtVm') return true; /* { if (!gInBackground) { FSMakeFSSpec(vRefNum, dirID, fileName, &theSpec); FSpDelete(&theSpec); StopSpinning(&qd.arrow); FWNoteAlert(CenterAlert(rQuickTimeVMAlert), gGenericFilter); StartSpinning(); } }*/ block.hFileInfo.ioFDirIndex++; block.hFileInfo.ioDirID = dirID; } } return false; } //===================================================================================== // Boolean HasVirtualMemory(void) //===================================================================================== // Returns true if the current system is running with virtual memory. //===================================================================================== extern Boolean HasVirtualMemory(void) { long physical, logical; if (Gestalt(gestaltPhysicalRAMSize, &physical) == noErr && Gestalt(gestaltLogicalRAMSize, &logical) == noErr) { return (physical < (logical - 512L * 1024L)); } return false; } \ No newline at end of file diff --git a/Source/C/Quantize.c b/Source/C/Quantize.c new file mode 100644 index 0000000..07716be --- /dev/null +++ b/Source/C/Quantize.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "Quantize.h" //===================================================================================== // Constants local to this module //===================================================================================== enum { kRedScale = 4, kGreenScale = 5, kBlueScale = 3 }; //===================================================================================== // Box: structure for holding information about color reduction boxes //===================================================================================== typedef struct Box { ushort c0min, c0max, c1min, c1max, c2min, c2max; ulong colorCount; } Box, *BoxPtr, **BoxHandle; //===================================================================================== // FillData: structure for passing information between C and assembly portions of the // histogram filling routine //===================================================================================== typedef struct FillData { ulong height, width; ulong rowBytes; ushort *histogram; uchar *baseAdr; } FillData, *FillDataPtr; //===================================================================================== // Global variables local to this module //===================================================================================== static ushort gNumBoxes, *gHistogram; static Box gBoxList[256]; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static BoxPtr FindBiggestPixelPop(void); static BoxPtr FindBiggestVolume(void); static void UpdateBox(BoxPtr boxp); static void MedianCut(short desiredColors); static void ComputeColor(BoxPtr boxp, int icolor, PaletteHandle thePalette); #if THINK_C || !USE_ASM static void DoFillHistogram32(FillDataPtr theData); static void DoFillHistogram16(FillDataPtr theData); #else extern void DoFillHistogram32(FillDataPtr theData); extern void DoFillHistogram16(FillDataPtr theData); #endif //===================================================================================== // OSErr DoQuantize(ImageHandle theImage, long numColors, PaletteHandle *thePalette) // // Calculates two-pass color quantization for a given image, reducing it to the // specified number of colors and returning the result as a palette in the specified // handle. // // External calls: KeepSpinning, CheckedNewHandle, ClearMem, DrawImage, KillGWorld //===================================================================================== extern OSErr DoQuantize(ImageHandle theImage, long numColors, PaletteHandle *thePalette, NestedProgressPtr progProc) { Boolean hadGWorld = ((*theImage)->gworld != nil); OSErr theErr = noErr; Handle theHandle; Str32 theNum; *thePalette = nil; KeepSpinning(); if (theHandle = CheckedNewHandle(32768L * sizeof(short), true)) { NumToString(numColors, theNum); SetSlideControlsText(gString[strSlideReducing], (*theImage)->file.name, gNullString, gNullString); UpdateParamText(gString[strReducingTo], theNum, gNullString, (*theImage)->file.name); HLockHi(theHandle); ClearMem(*theHandle, 32768L * sizeof(short)); gHistogram = (ushort *)StripAddress(*theHandle); if (!GWOrigSize(theImage)) KillGWorld(theImage); KeepSpinning(); theErr = DrawImage(theImage, bfQuantize + (gSlideShow ? bfUseSlideProgress : 0), progProc); HUnlock(theHandle); if (theErr == noErr) theErr = QuantizeFromHistogram(theHandle, numColors, thePalette); DisposeHandle(theHandle); } else gIntError = errNoQuantMemory, theErr = memFullErr; if (theErr != noErr) { if (!hadGWorld && (*theImage)->gworld) KillGWorld(theImage); } return theErr; } //===================================================================================== // QuantizeFromHistogram(Handle theHistogram, short numColors, // PaletteHandle *thePalette) // // Performs two-pass color reduction, given a histogram of color counts. // // External calls: KeepSpinning //===================================================================================== extern OSErr QuantizeFromHistogram(Handle theHistogram, long numColors, PaletteHandle *thePalette) { char hState = HGetState(theHistogram); OSErr theErr = noErr; RGBColor theColor; ushort i; HLock(theHistogram); gHistogram = (ushort *)StripAddress(*theHistogram); *thePalette = nil; if (*thePalette = NewPalette(numColors, nil, pmTolerant, 0)) { KeepSpinning(); gNumBoxes = 1; gBoxList[0].c0min = gBoxList[0].c1min = gBoxList[0].c2min = 0; gBoxList[0].c0max = gBoxList[0].c1max = gBoxList[0].c2max = 31; UpdateBox(&gBoxList[0]); KeepSpinning(); MedianCut(numColors - 2); KeepSpinning(); for (i = 0; i < gNumBoxes; i++) ComputeColor(&gBoxList[i], i, *thePalette); KeepSpinning(); for ( ; i < numColors; i++) { GetEntryColor(gGreyPalette[8], i, &theColor); SetEntryColor(*thePalette, i, &theColor); } KeepSpinning(); } else gIntError = errNoQuantMemory, theErr = memFullErr; HSetState(theHistogram, hState); return theErr; } //===================================================================================== // void ShrinkGWorld(ImageHandle theImage) // // Attempts to create a properly-sized GWorld from an overly-deep GWorld. // // External calls: PushPort, SlideProgress, MySetPort, MakeImageGWorld, KillGWorld, // PopPort, NewBits, KeepSpinning, OldBits //===================================================================================== extern OSErr ShrinkGWorld(ImageHandle theImage) { GWorldPtr oldGWorld = (*theImage)->gworld, newGWorld; JVDrawParamsHandle theParams; Rect srcRect, dstRect; OSErr theErr = noErr; // first we try to allocate a proper-sized GWorld KeepSpinning(); (*theImage)->gworld = nil; (*theImage)->flags &= ~ifGWOrigSize; if (!MakeImageGWorld(theImage, false)) { // if it didn't work, restore things and kill the oversized GWorld (*theImage)->gworld = oldGWorld; KillGWorld(theImage); return noErr; } // calculate source and destination rectangles srcRect = (GWOrigSize(theImage)) ? (*theImage)->crect : oldGWorld->portRect; dstRect = (*theImage)->gworld->portRect; // allocate the drawing parameters if (theParams = NewDrawParams(&(*theImage)->gworld->portRect, (*theImage)->quality, false, nil, (*theImage)->privateData)) { // set up the destination port and preflight our drawing SetUpDrawPort(theParams, kOffscreenPort1, (*theImage)->gworld, &srcRect, &dstRect, true); theErr = PreflightDrawing(theParams); // if everything worked, copy from GWorld to GWorld, and postflight when done if (theErr == noErr) { SpinIndef(); CopyGWorldToGWorld(oldGWorld, (*theParams)->dummy, &srcRect, &srcRect, srcCopy, nil); theErr = PostflightDrawing(theParams); } // now kill the old GWorld through the proper channels KeepSpinning(); newGWorld = (*theImage)->gworld; (*theImage)->gworld = oldGWorld; KillGWorld(theImage); (*theImage)->gworld = newGWorld; // dispose of everything and clean up DisposeHandle((Handle)theParams); } else theErr = MemError(); return theErr; } //===================================================================================== // void FillHistogram(PixMapPtr thePixMap) // // Fills the local histogram according to the data in the specified PixMap. Works // for 16-bit and 32-bit deep PixMaps. Both C and 68020 assembly versions are // provided. // // External calls: none //===================================================================================== extern void FillHistogram(PixMapPtr thePixMap) { register short theDepth = thePixMap->pixelSize; char mmuMode = true32b; FillData theData; theData.height = Height(&thePixMap->bounds); theData.width = Width(&thePixMap->bounds); theData.rowBytes = thePixMap->rowBytes & 0x3fff; theData.histogram = gHistogram; if (thePixMap->pmVersion == 4) theData.baseAdr = (uchar *)thePixMap->baseAddr; else theData.baseAdr = (uchar *)StripAddress(thePixMap->baseAddr); SwapMMUMode(&mmuMode); switch (theDepth) { case 32: DoFillHistogram32(&theData); break; case 16: DoFillHistogram16(&theData); break; } SwapMMUMode(&mmuMode); } //===================================================================================== // BoxPtr FindBiggestPixelPop(void) // // Searches the box list for the box with the largest number of pixels. // // External calls: none //===================================================================================== static BoxPtr FindBiggestPixelPop(void) { register ulong max = 0; register BoxPtr boxp; BoxPtr which = nil; register ushort i; for (i = 0, boxp = gBoxList; i < gNumBoxes; i++, boxp++) if (boxp->colorCount > max) if ((boxp->c0max > boxp->c0min) || (boxp->c1max > boxp->c1min) || (boxp->c2max > boxp->c2min)) { which = boxp; max = boxp->colorCount; } return which; } //===================================================================================== // BoxPtr FindBiggestVolume(void) // // Searches the box list for the box with the largest volume (actually largest norm). // // External calls: none //===================================================================================== static BoxPtr FindBiggestVolume(void) { register ulong norm, c0, c1, c2; register ulong max = 0; register BoxPtr boxp; BoxPtr which = nil; register ushort i; for (i = 0, boxp = gBoxList; i < gNumBoxes; i++, boxp++) { c0 = (boxp->c0max - boxp->c0min) * kRedScale; c1 = (boxp->c1max - boxp->c1min) * kGreenScale; c2 = (boxp->c2max - boxp->c2min) * kBlueScale; norm = c0*c0 + c1*c1 + c2*c2; if (norm > max) { which = boxp; max = norm; } } return which; } //===================================================================================== // void UpdateBox(BoxPtr boxp) // // Shrinks a given box to its minimum size and recalculates the number of pixels // contained therein. // // External calls: none //===================================================================================== static void UpdateBox(BoxPtr boxp) { short c0min, c0max, c1min, c1max, c2min, c2max; register short c0, c1, c2; register ushort *hist; ulong ccount; c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; if (c0max > c0min) for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { hist = gHistogram + (((c0 << 5) + c1) << 5) + c2min; for (c2 = c2min; c2 <= c2max; c2++) if (*hist++) { boxp->c0min = c0min = c0; goto haveC0Min; } } haveC0Min: if (c0max > c0min) for (c0 = c0max; c0 >= c0min; c0--) for (c1 = c1min; c1 <= c1max; c1++) { hist = gHistogram + (((c0 << 5) + c1) << 5) + c2min; for (c2 = c2min; c2 <= c2max; c2++) if (*hist++) { boxp->c0max = c0max = c0; goto haveC0Max; } } haveC0Max: if (c1max > c1min) for (c1 = c1min; c1 <= c1max; c1++) for (c0 = c0min; c0 <= c0max; c0++) { hist = gHistogram + (((c0 << 5) + c1) << 5) + c2min; for (c2 = c2min; c2 <= c2max; c2++) if (*hist++) { boxp->c1min = c1min = c1; goto haveC1Min; } } haveC1Min: if (c1max > c1min) for (c1 = c1max; c1 >= c1min; c1--) for (c0 = c0min; c0 <= c0max; c0++) { hist = gHistogram + (((c0 << 5) + c1) << 5) + c2min; for (c2 = c2min; c2 <= c2max; c2++) if (*hist++) { boxp->c1max = c1max = c1; goto haveC1Max; } } haveC1Max: if (c2max > c2min) for (c2 = c2min; c2 <= c2max; c2++) for (c0 = c0min; c0 <= c0max; c0++) { hist = gHistogram + (((c0 << 5) + c1min) << 5) + c2; for (c1 = c1min; c1 <= c1max; c1++, hist += 32) if (*hist) { boxp->c2min = c2min = c2; goto haveC2Min; } } haveC2Min: if (c2max > c2min) for (c2 = c2max; c2 >= c2min; c2--) for (c0 = c0min; c0 <= c0max; c0++) { hist = gHistogram + (((c0 << 5) + c1min) << 5) + c2; for (c1 = c1min; c1 <= c1max; c1++, hist += 32) if (*hist) { boxp->c2max = c2max = c2; goto haveC2Max; } } haveC2Max: ccount = 0; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { hist = gHistogram + (((c0 << 5) + c1) << 5) + c2min; for (c2 = c2min; c2 <= c2max; c2++) ccount += *hist++; } boxp->colorCount = ccount; } //===================================================================================== // void MedianCut(short desiredColors) // // Repeatedly divides the original box into smaller boxes until we have as many boxes // as there are desired colors. // // External calls: KeepSpinning //===================================================================================== static void MedianCut(short desiredColors) { long c0min, c0max, c1min, c1max, c2min, c2max; long c0, c1, c2, cmax; register BoxPtr b1, b2; ushort n, lb; while (gNumBoxes < desiredColors) { KeepSpinning(); if ((gNumBoxes << 1) <= desiredColors) b1 = FindBiggestPixelPop(); else b1 = FindBiggestVolume(); if (!b1) break; c0min = b1->c0min; c0max = b1->c0max; c1min = b1->c1min; c1max = b1->c1max; c2min = b1->c2min; c2max = b1->c2max; b2 = &gBoxList[gNumBoxes]; b2->c0max = c0max; b2->c1max = c1max; b2->c2max = c2max; b2->c0min = c0min; b2->c1min = c1min; b2->c2min = c2min; c0 = (c0max - c0min) * kRedScale; c1 = (c1max - c1min) * kGreenScale; c2 = (c2max - c2min) * kBlueScale; cmax = c0; n = 0; if (c1 > cmax) { cmax = c1; n = 1; } if (c2 > cmax) n = 2; switch (n) { case 0: lb = (c0max + c0min) >> 1; b1->c0max = lb; b2->c0min = lb + 1; break; case 1: lb = (c1max + c1min) >> 1; b1->c1max = lb; b2->c1min = lb + 1; break; case 2: lb = (c2max + c2min) >> 1; b1->c2max = lb; b2->c2min = lb + 1; break; } UpdateBox(b1); UpdateBox(b2); gNumBoxes++; } } //===================================================================================== // void ComputeColor(BoxPtr boxp, int icolor, PaletteHandle thePalette) // // Calculates the final RGB color by doing a weighted average over pixels in the // given box. // // External calls: none //===================================================================================== static void ComputeColor(BoxPtr boxp, int icolor, PaletteHandle thePalette) { ulong count, total = 0, c0total = 0, c1total = 0, c2total = 0; short c0min, c0max, c1min, c1max, c2min, c2max; short c0, c1, c2, r, g, b; register ushort *hist; RGBColor theColor; if (!icolor) { theColor.red = theColor.blue = theColor.green = 0xffff; SetEntryColor(thePalette, 0, &theColor); theColor.red = theColor.blue = theColor.green = 0; SetEntryColor(thePalette, 1, &theColor); } c0min = boxp->c0min; c0max = boxp->c0max; c1min = boxp->c1min; c1max = boxp->c1max; c2min = boxp->c2min; c2max = boxp->c2max; for (c0 = c0min; c0 <= c0max; c0++) for (c1 = c1min; c1 <= c1max; c1++) { hist = gHistogram + (((c0 << 5) + c1) << 5) + c2min; for (c2 = c2min; c2 <= c2max; c2++) if (count = *hist++) { total += count; c0total += ((c0 << 3) + 4) * count; c1total += ((c1 << 3) + 4) * count; c2total += ((c2 << 3) + 4) * count; } } if (total) { r = (c0total + (total >> 1)) / total; g = (c1total + (total >> 1)) / total; b = (c2total + (total >> 1)) / total; theColor.red = ((ushort)r << 8) | (ushort)r; theColor.green = ((ushort)g << 8) | (ushort)g; theColor.blue = ((ushort)b << 8) | (ushort)b; } else theColor.red = theColor.green = theColor.blue = 0; SetEntryColor(thePalette, icolor + 2, &theColor); } #if !USE_ASM //===================================================================================== // Generic C substitutes for the assembly functions defined below. //===================================================================================== static void DoFillHistogram32(FillDataPtr theData) { #include "FillHistogram32.c" } static void DoFillHistogram16(FillDataPtr theData) { #include "FillHistogram16.c" } #elif THINK_C //===================================================================================== // Assembly language interfaces for THINK C; here we define the offsets of all fields // within the CopyData structure, and then provide C function wrappers around asm { } // statements that #include the actual assembly code. In MPW, we just need to compile // Quantize.a to get the assembly routines. //===================================================================================== #define height offsetof(FillData, height) /* 0 */ #define width offsetof(FillData, width) /* 4 */ #define rowBytes offsetof(FillData, rowBytes) /* 8 */ #define histogram offsetof(FillData, histogram) /* 12 */ #define baseAdr offsetof(FillData, baseAdr) /* 16 */ static void DoFillHistogram32(FillDataPtr theData) { asm { #include "FillHistogram32.a" } } static void DoFillHistogram16(FillDataPtr theData) { asm { #include "FillHistogram16.a" } } #endif \ No newline at end of file diff --git a/Source/C/QuickDrawUtils.c b/Source/C/QuickDrawUtils.c new file mode 100644 index 0000000..87bf295 --- /dev/null +++ b/Source/C/QuickDrawUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "QuickDrawUtils.h" //===================================================================================== // PortStackItem: structure to store port and device information for when we push/pop // the current port. //===================================================================================== typedef struct PortStackItem { CGrafPtr port; GDHandle device; } PortStackItem, *PortStackPtr, **PortStackHandle; //===================================================================================== // Global variables local to this module //===================================================================================== static PortStackItem gPortStack[64]; static PortStackPtr gPortStackPtr = gPortStack; //===================================================================================== // void PushPort(void) // // Pushes the current port and device onto the port stack. // // External calls: none //===================================================================================== void PushPort(void) { GetGWorld(&gPortStackPtr->port, &gPortStackPtr->device); gPortStackPtr++; } //===================================================================================== // void PopPort(void) // // Pops a port and device from the port stack into the current graphics environment. // // External calls: none //===================================================================================== void PopPort(void) { gPortStackPtr--; SetGWorld(gPortStackPtr->port, gPortStackPtr->device); } //===================================================================================== // void MySetPort(CGrafPtr thePort) // // Sets the current port; if nil is passed as the port, the current port is set to // the window manager's port. // // External calls: none //===================================================================================== void MySetPort(CGrafPtr thePort) { if (!thePort) GetCWMgrPort(&thePort); if (thePort) SetGWorld(thePort, nil); } extern GWorldPtr NewTempGWorld(short width, short height, short depth, CTabHandle colors) { Boolean oldState = GetQDxDispatchPatchState(); GWorldPtr theGWorld = nil; OSErr theErr = noErr; Rect theRect; SetRect(&theRect, 0, 0, width, height); do { InstallQDxDispatchPatch(false); theErr = NewGWorld(&theGWorld, depth, &theRect, colors, nil, keepLocal + useTempMem); SetQDxDispatchPatchState(oldState); if (theErr != noErr) { if (IsMemAvailable(EstGWorldSize(&theRect, depth))) theErr = NewGWorld(&theGWorld, depth, &theRect, colors, nil, keepLocal); else theErr = memFullErr; } if (theErr != noErr) { if (theRect.bottom == 8) { theGWorld = nil; break; } theRect.bottom -= height / 8; if (theRect.bottom < 8) theRect.bottom = 8; } } while (theErr != noErr); return (theErr == noErr) ? theGWorld : nil; } //===================================================================================== // GWorldPtr MyNewGWorld(Rect *theRect, short theDepth, CTabHandle theColors, // GDHandle theDevice, Boolean whiteBack, Boolean inTempMem) // // Creates a new GWorld, erases it, and initializes the colors. // // External calls: none //===================================================================================== GWorldPtr MyNewGWorld(Rect *theRect, short theDepth, CTabHandle theColors, GDHandle theDevice, Boolean whiteBack, Boolean inTempMem) { Boolean oldState = GetQDxDispatchPatchState(); long flags = keepLocal; GWorldPtr theGWorld; PushPort(); MySetPort(nil); if (inTempMem) { flags += useTempMem; InstallQDxDispatchPatch(false); } if (NewGWorld(&theGWorld, theDepth, theRect, theColors, theDevice, flags) == noErr) { MySetPort(theGWorld); LockPixels(GetGWorldPixMap(theGWorld)); RectRgn(theGWorld->visRgn, theRect); RectRgn(theGWorld->clipRgn, theRect); RGBForeColor(&gBlack); RGBBackColor(&gWhite); if (!whiteBack) PaintRect(theRect); else EraseRect(theRect); UnlockPixels(GetGWorldPixMap(theGWorld)); PopPort(); if (inTempMem) SetQDxDispatchPatchState(oldState); return theGWorld; } PopPort(); if (inTempMem) SetQDxDispatchPatchState(oldState); return nil; } extern void MaxRect(Rect *srcRect, Rect *boundingRect, Rect *dstRect) { dstRect->top = dstRect->left = 0; if (Width(srcRect) > Height(srcRect)) { dstRect->right = Width(boundingRect); dstRect->bottom = (long)Height(srcRect) * Width(boundingRect) / (long)Width(srcRect); } else { dstRect->right = (long)Width(srcRect) * Height(boundingRect) / (long)Height(srcRect); dstRect->bottom = Height(boundingRect); } OffsetRect(dstRect, boundingRect->left, boundingRect->top); } extern void MaxSquare(Rect *srcRect, Rect *squareRect) { *squareRect = *srcRect; if (Width(srcRect) > Height(srcRect)) { squareRect->left += (Width(srcRect) - Height(srcRect)) >> 1; squareRect->right = squareRect->left + Height(srcRect); } else { squareRect->top += (Height(srcRect) - Width(srcRect)) >> 1; squareRect->bottom = squareRect->top + Width(srcRect); } } extern void CopyGWorldToGWorld(GWorldPtr gw1, GWorldPtr gw2, Rect *srcRect, Rect *dstRect, short mode, RgnHandle mask) { PixMapHandle pm1 = GetGWorldPixMap(gw1), pm2 = GetGWorldPixMap(gw2); GWorldFlags state1 = GetPixelsState(pm1), state2 = GetPixelsState(pm2); char hstate1 = HGetState((Handle)pm1), hstate2 = HGetState((Handle)pm2); PushPort(); MySetPort(gw2); HLock((Handle)pm1); HLock((Handle)pm2); LockPixels(pm1); LockPixels(pm2); CopyBits((BitMap *)*pm1, (BitMap *)*pm2, srcRect, dstRect, mode, mask); SetPixelsState(pm1, state1); SetPixelsState(pm2, state2); HSetState((Handle)pm1, hstate1); HSetState((Handle)pm2, hstate2); PopPort(); } //===================================================================================== // void GlobalRect(Rect *theRect, WindowPtr theWindow) // // Converts the given rectangle to global coordinates, relative to the window. // // External calls: none //===================================================================================== void GlobalRect(Rect *theRect, WindowPtr theWindow) { Boolean change = (theWindow != qd.thePort); Point thePoint = { 0, 0 }; if (change) { PushPort(); MySetPort((CGrafPtr)theWindow); } LocalToGlobal(&thePoint); if (change) PopPort(); OffsetRect(theRect, thePoint.h, thePoint.v); } //===================================================================================== // void GlobalRgn(RgnHandle theRgn, WindowPtr theWindow) // // Converts the given region to global coordinates, relative to the window. // // External calls: none //===================================================================================== void GlobalRgn(RgnHandle theRgn, WindowPtr theWindow) { Boolean change = (theWindow != qd.thePort); Point thePoint = { 0, 0 }; if (change) { PushPort(); MySetPort((CGrafPtr)theWindow); } LocalToGlobal(&thePoint); if (change) PopPort(); OffsetRgn(theRgn, thePoint.h, thePoint.v); } //===================================================================================== // void LocalRect(Rect *theRect, WindowPtr theWindow) // // Converts the given rectangle to local coordinates, relative to the window. // // External calls: none //===================================================================================== void LocalRect(Rect *theRect, WindowPtr theWindow) { Boolean change = (theWindow != qd.thePort); Point thePoint = { 0, 0 }; if (change) { PushPort(); MySetPort((CGrafPtr)theWindow); } GlobalToLocal(&thePoint); if (change) PopPort(); OffsetRect(theRect, thePoint.h, thePoint.v); } //===================================================================================== // void LocalRgn(RgnHandle theRgn, WindowPtr theWindow) // // Converts the given region to local coordinates, relative to the window. // // External calls: none //===================================================================================== void LocalRgn(RgnHandle theRgn, WindowPtr theWindow) { Boolean change = (theWindow != qd.thePort); Point thePoint = { 0, 0 }; if (change) { PushPort(); MySetPort((CGrafPtr)theWindow); } GlobalToLocal(&thePoint); if (change) PopPort(); OffsetRgn(theRgn, thePoint.h, thePoint.v); } //===================================================================================== // Boolean Clipped(Rect *theRect, RgnHandle clipRgn) // // Determines if the given rectangle is clipped by the region. // // External calls: none //===================================================================================== Boolean Clipped(Rect *theRect, RgnHandle clipRgn) { RgnHandle rectRgn, clippedRgn; Boolean result = false; if (!clipRgn || !theRect) return false; if (rectRgn = NewRgn()) { if (clippedRgn = NewRgn()) { RectRgn(rectRgn, theRect); SectRgn(rectRgn, clipRgn, clippedRgn); result = !EqualRgn(rectRgn, clippedRgn); DisposeRgn(clippedRgn); } DisposeRgn(rectRgn); } return result; } \ No newline at end of file diff --git a/Source/C/RequiredEventHandlers.c b/Source/C/RequiredEventHandlers.c new file mode 100644 index 0000000..7679a91 --- /dev/null +++ b/Source/C/RequiredEventHandlers.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif static ImageHandle ImageFromSpec(FSSpec *theFile); static OSErr DrawToPrinter(ImageHandle theImage, NestedProgressPtr progProc); static OSErr GetPrintParams(void); static pascal void PrintIdleProc(void); static short gOurResFile; static PrIdleUPP gPrintIdle = nil; static JVDrawParamsHandle gPrintParams; /* * HandleOpenApplication(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the open application event; does one of four * tasks upon startup, as specified in the preferences * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleOpenApplication(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(theEvent, reply, refCon) #endif WindowPtr front = FWFrontWindow(); OSErr theErr; if (gInBackground) return noErr; if (front && (GetWRefCon(front) == kHelpWindowID)) return noErr; switch (gThePrefs.startWith) { case swAutoSlide: theErr = DoSlideShow(); break; case swSlide: HandleMenuChoice(MakeMenuSelection(rFileMenu, fileSlideItem)); break; case swOpen: HandleMenuChoice(MakeMenuSelection(rFileMenu, fileOpenItem)); break; case swNone: break; } return noErr; } /* * GetOpenDefaults(openScreen, openFull, openPalette, drawQuality) * * Purpose: Translates the current prefs into enumerated parameters for opening * Inputs: openScreen = pointer to DescType to hold enumerated open screen * openFull = pointer to DescType to hold enumerated full screen mode * openPalette = pointer to DescType to hold enumerated palette * drawQuality = pointer to DescType to hold enumerated drawing quality * Returns: nothing * */ void GetOpenDefaults(DescType *openScreen, DescType *openFull, DescType *openPalette, DescType *drawQuality) { switch (gThePrefs.openScreen) { case osDeepest: *openScreen = (gThePrefs.pickColor) ? kAEOSDeepestColor : kAEOSDeepestGray; break; case osLargest: *openScreen = (gThePrefs.pickColor) ? kAEOSLargestColor : kAEOSLargestGray; break; case osMain: *openScreen = kAEOSMain; break; } switch (gThePrefs.openFull) { case ofNoMatterWhat: *openFull = kAEOFAlways; break; case ofAlways: *openFull = kAEOFAlwaysIfLarge; break; case ofAsk: *openFull = kAEOFAskIfLarge; break; case ofNever: *openFull = kAEOFNever; break; } switch (gThePrefs.autoQuant) { case aqAlways: *openPalette = (gThePrefs.imagePalette) ? kAEOPQuantImageScrn : kAEOPQuantScrn; break; case aqOnly: *openPalette = (gThePrefs.imagePalette) ? kAEOPImageQuantScrn : kAEOPQuantScrn; break; case aqNever: *openPalette = (gThePrefs.imagePalette) ? kAEOPImageScrn : kAEOPScrn; break; } switch (gThePrefs.imageQuality) { case iqVHigh: *drawQuality = kAEDQVeryHigh; break; case iqHigh: *drawQuality = kAEDQHigh; break; case iqMedium: *drawQuality = kAEDQNormal; break; } } /* * HandleOpenDocuments(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the open document event; accepts the input files * one at a time and opens them in succession by calling OpenDocument * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleOpenDocuments(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(reply, refCon) #endif Boolean autoExpand, openVisible, openBitmaps, autoComments, fixTypes, fixCreator; DescType returnedType, openScreen, openFull, openPalette, drawQuality; long theCount, theIndex; OSErr theErr = noErr; AEDescList theList; AEKeyword theKey; Boolean noErrors; Size actualSize; FSSpec theFile; FInfo theInfo; AEBegin(); theErr = AEGetParamDesc(theEvent, keyDirectObject, typeWildCard, &theList); if ((theErr == noErr) && (theList.descriptorType != typeObjectSpecifier)) { GetOpenDefaults(&openScreen, &openFull, &openPalette, &drawQuality); theErr = AEExtractEnumerated(theEvent, keyOpenScreen, &returnedType); if (theErr == noErr) openScreen = returnedType; theErr = AEExtractEnumerated(theEvent, keyOpenFull, &returnedType); if (theErr == noErr) openFull = returnedType; theErr = AEExtractBoolean(theEvent, keyAutoExpand, &autoExpand); if (theErr != noErr) autoExpand = gThePrefs.expandSmall; theErr = AEExtractBoolean(theEvent, keyVisible, &openVisible); if (theErr != noErr) openVisible = true; theErr = AEExtractEnumerated(theEvent, keyOpenPalette, &returnedType); if (theErr == noErr) openPalette = returnedType; theErr = AEExtractEnumerated(theEvent, keyOpenQuality, &returnedType); if (theErr == noErr) drawQuality = returnedType; theErr = AEExtractBoolean(theEvent, keyOpenBitmaps, &openBitmaps); if (theErr != noErr) openBitmaps = (gThePrefs.useBitmaps == ubAlways); theErr = AEExtractBoolean(theEvent, keyAutoComments, &autoComments); if (theErr != noErr) autoComments = gThePrefs.autoComments; theErr = AEExtractBoolean(theEvent, keyFixTypes, &fixTypes); if (theErr != noErr) fixTypes = gThePrefs.autoFix; theErr = AEExtractBoolean(theEvent, keyChangeCreator, &fixCreator); if (theErr != noErr) fixCreator = gThePrefs.changeCreator; theErr = AEExtractBoolean(theEvent, keyNoErrors, &noErrors); if (theErr != noErr) noErrors = false; DisableMenus(); if (gThePrefs.onlyOne && !gSlideShow) while (gImageRoot) SendCloseWindow((*LastImage())->window); theErr = AECountItems(&theList, &theCount); if (gThePrefs.onlyOne) theCount = 1; if (theErr == noErr) { for (theIndex = 1; theIndex <= theCount; theIndex++) { theErr = AEGetNthPtr(&theList, theIndex, typeFSS, &theKey, &returnedType, (void *)&theFile, sizeof(FSSpec), &actualSize); if (theErr == noErr) { if (FSpGetFInfo(&theFile, &theInfo) != noErr || theInfo.fdType == kPrefsType || theInfo.fdType == kHelpType) continue; StartSpinning(); theErr = DoOpenDocument(&theFile, theIndex == 1, openScreen, openFull, autoExpand, openVisible, openPalette, drawQuality, openBitmaps, autoComments, fixTypes, fixCreator); if (!noErrors) HandleAEError(theErr, errNoLoadMemory, theFile.name); } else { theErr = errAEBadListItem; break; } } } else theErr = errAEWrongDataType; AEDisposeDesc(&theList); StopSpinning(&qd.arrow); } EnableMenus(); AEEnd(); return theErr; } pascal OSErr HandlePrintDocuments(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(reply, refCon) #endif OSErr theErr = noErr; ImageHandle theImage; AEDescList theList; AEBegin(); theErr = AEGetParamDesc(theEvent, keyDirectObject, typeWildCard, &theList); if (theErr == noErr) { DisableMenus(); StartSpinning(); if (theList.descriptorType != typeObjectSpecifier) { long theCount, theIndex; DescType returnedType; AEKeyword theKey; Size actualSize; FSSpec theFile; theErr = AECountItems(&theList, &theCount); if (theErr == noErr) { for (theIndex = 1; theIndex <= theCount; theIndex++) { theErr = AEGetNthPtr(&theList, theIndex, typeFSS, &theKey, &returnedType, (void *)&theFile, sizeof(FSSpec), &actualSize); if (theErr == noErr) { theErr = DoOpenDocument(&theFile, false, kAEOSMain, kAEOFNever, false, false, kAEOPScrn, kAEDQNormal, false, false, false, false); if (theErr != noErr) HandleAEError(theErr, errNoPrintMemory, theFile.name); else theImage = ImageFromSpec(&theFile); if (theImage) { theErr = DoPrintDocument(theImage, theIndex == 1); if (theErr != noErr) { if (theErr == codecAbortErr) { theErr = noErr; break; } HandleAEError(theErr, errNoPrintMemory, theFile.name); } DoCloseWindow((*theImage)->window, false); } } else { theErr = errAEBadListItem; break; } } } else theErr = errAEWrongDataType; } else { ObjectTokenHandle theToken; AEDesc theObject; short count, i; theErr = AEExtractObject(&theList, 0, &theObject); if (theErr == noErr) { theToken = (ObjectTokenHandle)theObject.dataHandle; if (theObject.descriptorType == cWindow || theObject.descriptorType == cDocument) { count = (*theToken)->count; for (i = 0; i < count; i++) { if (theErr == noErr) theErr = DoPrintDocument(FindImage((WindowPtr)(*theToken)->object[i]), i == 0); } } else theErr = errAEEventNotHandled; AEDisposeDesc(&theObject); } } AEDisposeDesc(&theList); StopSpinning(&qd.arrow); } EnableMenus(); AEEnd(); return theErr; } static ImageHandle ImageFromSpec(FSSpec *theFile) { ImageHandle theImage; for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if (SameFile(&(*theImage)->file, theFile)) return theImage; return nil; } extern OSErr DoPrintDocument(ImageHandle theImage, Boolean first) { NestedProgress progProc = { { nil, 0 }, 0, 0L, 0x10000L, false }; TPrStatus printStatus; WindowPtr frontWindow; OSErr theErr = noErr; TPPrPort printPort; // initialize the progress proc, and save a reference to our current resource file progProc.prog.progressProc = gGenericProgress; progProc.prog.progressRefCon = (long)&progProc; gOurResFile = CurResFile(); // open the driver and, if this is the first document, handle the print dialog PrOpen(); if (first) { theErr = GetPrintParams(); if (theErr != noErr) return theErr; } // call the progress procedure to open the printing... dialog UpdateParamText(gString[strPrinting], gNullString, gNullString, (*theImage)->file.name); CallICMProgressProc(progProc.prog.progressProc, codecProgressOpen, kModalProgress, progProc.prog.progressRefCon); // store a pointer to our idle procedure in the print record if (!gPrintIdle) gPrintIdle = NewPrIdleProc((ProcPtr)PrintIdleProc); (*gPrintRecord)->prJob.pIdleProc = gPrintIdle; // set up the proper document name if (frontWindow = FrontWindow()) { Str63 windowName; BlockMove((*theImage)->file.name, windowName, *(*theImage)->file.name + 1); SetWTitle(frontWindow, windowName); PrValidate(gPrintRecord); } // do the actual printing if ((printPort = PrOpenDoc(gPrintRecord, nil, nil)) && (theErr = PrError()) == noErr) { PrOpenPage(printPort, nil); if ((theErr = PrError()) == noErr) theErr = DrawToPrinter(theImage, &progProc); PrClosePage(printPort); } PrCloseDoc(printPort); // spool the printing, if necessary if ((*gPrintRecord)->prJob.bJDocLoop == bSpoolLoop && theErr == noErr) { PrPicFile(gPrintRecord, nil, nil, nil, &printStatus); theErr = PrError(); } // close the outer progress, along with the printer driver, and exit CallICMProgressProc(progProc.prog.progressProc, codecProgressClose, kModalProgress, progProc.prog.progressRefCon); PrClose(); return theErr; } static OSErr DrawToPrinter(ImageHandle theImage, NestedProgressPtr progProc) { Rect printRect, srcRect, dstRect, boundsRect; NestedProgress innerProg; OSErr theErr = noErr; // get the printing rectangle, and inset it by 1/2 inch on all sides printRect = (*gPrintRecord)->prInfo.rPage; InsetRect(&printRect, (*gPrintRecord)->prInfo.iHRes / 2, (*gPrintRecord)->prInfo.iVRes / 2); // calculate the appropriate source/destination rectangles srcRect = (*theImage)->crect; MaxRect(&srcRect, &printRect, &dstRect); OffsetRect(&dstRect, (Width(&printRect) - Width(&dstRect)) / 2, (Height(&printRect) - Height(&dstRect)) / 2); ClipRect(&dstRect); boundsRect = (*theImage)->grect; // set up the bounds of the progress procedure used during drawing innerProg = *progProc; innerProg.begin = 0x00001000L; innerProg.end = 0x0000F000L; // allocate and initialize the drawing parameters if (gPrintParams = NewDrawParams(&boundsRect, iqMedium, false, &innerProg, (*theImage)->privateData)) { SetUpDrawPort(gPrintParams, kOnscreenPort, (CGrafPtr)qd.thePort, &srcRect, &dstRect, false); // preflight the drawing here and save the port KeepSpinning(); theErr = PreflightDrawing(gPrintParams); PushPort(); if (theErr == noErr) { // point to the dummy drawing port and start the inner progress proc MySetPort((*gPrintParams)->dummy); CallICMProgressProc((*gPrintParams)->progress.prog.progressProc, codecProgressOpen, kModalProgress, (*gPrintParams)->progress.prog.progressRefCon); // now do the drawing, either from the offscreen GWorld... if ((*theImage)->gworld && GWOrigSize(theImage)) CopyGWorldToGWorld((*theImage)->gworld, (*gPrintParams)->dummy, &(*theImage)->gworld->portRect, &(*theImage)->gworld->portRect, srcCopy, nil); // or from the image directly else theErr = (*theImage)->format->draw((*theImage)->data, gPrintParams); // clean up our drawing, checking for missed aborts if (theErr == noErr) theErr = PostflightDrawing(gPrintParams); else PostflightDrawing(gPrintParams); // if we were aborted, tell the printer so, and close the inner prog. if (theErr == codecAbortErr) PrSetError(iPrAbort); CallICMProgressProc((*gPrintParams)->progress.prog.progressProc, codecProgressClose, 0L, (*gPrintParams)->progress.prog.progressRefCon); KeepSpinning(); } PopPort(); DisposeHandle((Handle)gPrintParams); } return theErr; } static OSErr GetPrintParams(void) { OSErr theErr = AEInteractWithUser(kAEDefaultTimeout, &gTheNotification, gAEIdleProc); if (!gPrintRecord) { if (LoadPrefsHandle(kPrefsPrintType, 0, (Handle *)&gPrintRecord) != noErr) { if (!(gPrintRecord = (THPrint)NewHandle(sizeof(TPrint)))) return memFullErr; PrintDefault(gPrintRecord); } else PrValidate(gPrintRecord); } if (theErr != errAENoUserInteraction) { StopSpinning(&qd.arrow); FWDeactivate(); if (!PrJobDialog(gPrintRecord)) { FWActivate(); return codecAbortErr; } FWActivate(); StartSpinning(); SavePrefsHandle(kPrefsPrintType, 0, (Handle)gPrintRecord); } return theErr; } static pascal void PrintIdleProc(void) { short oldResFile = CurResFile(); UseResFile(gOurResFile); PushPort(); if (CheckAbort(gPrintParams)) PrSetError(iPrAbort); PopPort(); UseResFile(oldResFile); } /* * HandleQuitApplication(theEvent, reply, refCon) * * Purpose: AppleEvent handler for the quit application event; we set the done flag, * clean up all the windows, restore the menu bar, and return * Inputs: theEvent = the AppleEvent record * reply = the AppleEvent reply * refCon = our personal work variable * Returns: an OSErr with the overall result of the operation (i.e., noErr) * */ pascal OSErr HandleQuitApplication(AppleEvent *theEvent, AppleEvent *reply, long refCon) { #if applec #pragma unused(theEvent, reply, refCon) #endif AEBegin(); gDone = true; AEEnd(); return noErr; } \ No newline at end of file diff --git a/Source/C/SCRN.c b/Source/C/SCRN.c new file mode 100644 index 0000000..acfa195 --- /dev/null +++ b/Source/C/SCRN.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "SCRN.h" //===================================================================================== // SCRNPrivates: private data structure for SCRN images, maintained for each image. //===================================================================================== typedef struct SCRNPrivates SCRNPrivates, *SCRNPrivatesPtr, **SCRNPrivatesHandle; struct SCRNPrivates { OSType id; // id flag to be sure that we got the right privates Boolean oldFormat; // flag: true if this is an old-format image }; //===================================================================================== // Global variables local to this module //===================================================================================== static FSSpec gLastSpec; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr DecompressSCRNImage(uchar *dataStart, SCRNPrivatesHandle privates, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length); static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow); //===================================================================================== // Boolean idSCRN(uchar *theData, long theSize) //===================================================================================== // Examines the given data and attempts to identify it as a SCRN image. //===================================================================================== extern Boolean idSCRN(uchar *theData, long theSize, short refNum, FSSpec *theSpec) { #if applec #pragma unused(theData, theSize) #endif Boolean ok = false; OSErr theErr; long size; gLastSpec.vRefNum = 0; theErr = GetEOF(refNum, &size); if (theErr == noErr && size == (512 / 8 * 342)) ok = true; refNum = FSpOpenResFile(theSpec, fsRdPerm); if (refNum != -1) { Handle dummyHandle; SetResLoad(false); dummyHandle = GetResource(kPICTType, 0); if (dummyHandle) ReleaseResource(dummyHandle); SetResLoad(true); CloseResFile(refNum); if (dummyHandle) { gLastSpec = *theSpec; ok = true; } } return ok; } //===================================================================================== // OSErr LoadSCRN(short theFile, ImageHandle theImage) //===================================================================================== // Loads the SCRN image into memory from disk. //===================================================================================== extern OSErr LoadSCRN(short theFile, ImageHandle theImage) { OSErr theErr = noErr; KeepSpinning(); if (gLastSpec.vRefNum) { theFile = FSpOpenResFile(&gLastSpec, fsRdPerm); if (theFile != -1) { (*theImage)->data = GetResource(kPICTType, 0); if ((*theImage)->data) DetachResource((*theImage)->data); CloseResFile(theFile); if (!(*theImage)->data) gIntError = errNoLoadMemory, theErr = memFullErr; } else gIntError = errCantReadFile, theErr = ResError(); } else theErr = DefaultLoad(theFile, theImage); return theErr; } //===================================================================================== // OSErr OpenSCRN(ImageHandle theImage) //===================================================================================== // Initializes the image record for a SCRN image. //===================================================================================== extern OSErr OpenSCRN(ImageHandle theImage) { SCRNPrivatesHandle privates; OSErr theErr = noErr; if (!(privates = (SCRNPrivatesHandle)NewHandleClear(sizeof(SCRNPrivates)))) return memFullErr; (*theImage)->privateData = (Handle)privates; (*privates)->id = kSCRNType; (*privates)->oldFormat = (gLastSpec.vRefNum == 0); if ((*privates)->oldFormat) { (*theImage)->grect.right = 512; (*theImage)->grect.bottom = 342; (*theImage)->depth = 1; (*theImage)->qrect = (*theImage)->crect = (*theImage)->grect; (*theImage)->compression = 0; BlockMove(gString[strUncompressed], (*theImage)->compressionDesc, *gString[strUncompressed] + 1); } else { DisposeHandle((Handle)privates); (*theImage)->privateData = nil; theErr = OpenPICT(theImage); } return theErr; } //===================================================================================== // OSErr DrawSCRN(Handle theHandle, JVDrawParamsHandle theParams) //===================================================================================== // Draws a SCRN image into the specified GWorld, from the srcRect into the dstRect, // clipping as dstRgn specifies. //===================================================================================== extern OSErr DrawSCRN(Handle theHandle, JVDrawParamsHandle theParams) { SCRNPrivatesHandle privates = (SCRNPrivatesHandle)(*theParams)->privateData; NestedProgress theProgress = (*theParams)->progress; char hState = HGetState(theHandle); OSErr theErr = noErr; GWorldPtr theGWorld; uchar *dataStart; if (!privates || (*privates)->id != kSCRNType || !(*privates)->oldFormat) return DrawPICT(theHandle, theParams); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon); HLockHi(theHandle); if (theErr == noErr) { dataStart = (uchar *)StripAddress(*theHandle); theGWorld = NewTempGWorld(512, 342, 1, nil); if (theGWorld) { theErr = DecompressSCRNImage(dataStart, privates, GetGWorldPixMap(theGWorld), (ICMProgressProcRecordPtr)&theProgress, GetHandleSize(theHandle)); if ((*theParams)->progress.aborted) theErr = codecAbortErr; DisposeGWorld(theGWorld); } else gIntError = errNoDrawMemory, theErr = memFullErr; } HSetState(theHandle, hState); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon); return theErr; } //===================================================================================== // OSErr FixSCRN(ImageHandle theImage, Handle *finalData, Boolean palette) //===================================================================================== // Called to convert a JPEG image into a SCRN image; here we just convert it to a PICT // and then save. //===================================================================================== extern OSErr FixSCRN(ImageHandle theImage, Handle *finalData, Boolean palette) { return FixPICT(theImage, finalData, palette); } //===================================================================================== // OSErr SaveSCRN(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, // Rect *theRect, Handle privates) //===================================================================================== // Called to save a SCRN image to disk. //===================================================================================== extern OSErr SaveSCRN(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, Handle thePrivates) { SCRNPrivatesHandle privates = (SCRNPrivatesHandle)thePrivates; Handle resPict = theHandle; short theFile; OSErr theErr; if (privates && (*privates)->id == kSCRNType && (*privates)->oldFormat) return DefaultSave(theSpec, theHandle, thePreview, theRect, kSCRNType); if (MakeMemAvailable(GetHandleSize(theHandle))) { theErr = HandToHand(&resPict); if (theErr == noErr) { KeepSpinning(); FSpCreateResFile(theSpec, kCreator, kSCRNType, 0); KeepSpinning(); theFile = FSpOpenResFile(theSpec, fsRdWrPerm); if (theFile) { SpinIndef(); AddResource(resPict, kPICTType, 0, gString[strJPEGViewPICT]); if ((theErr = ResError()) == noErr) { WriteResource(resPict); KeepSpinning(); ReleaseResource(resPict); CloseResFile(theFile); return noErr; } else gIntError = errCantWriteFile; CloseResFile(theFile); } else gIntError = errCantOpenFile, theErr = fnOpnErr; FSpDelete(theSpec); DisposeHandle(resPict); } else gIntError = errNoSaveMemory, theErr = memFullErr; } else gIntError = errNoSaveMemory, theErr = memFullErr; KeepSpinning(); return theErr; } //===================================================================================== // OSErr DecompressSCRNImage(uchar *dataStart, SCRNPrivatesHandle privates, // PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length) //===================================================================================== // Oversees the decompression of a SCRN image, handling banding, and calling the // appropriate function to perform the actual decompression. //===================================================================================== static OSErr DecompressSCRNImage(uchar *dataStart, SCRNPrivatesHandle privates, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length) { #if applec #pragma unused(privates) #endif uchar *ptr, *rowStart, *dst, *dataEnd = dataStart + length; char pState = GetPixelsState(dstPixMap); RgnHandle dstRgn = qd.thePort->visRgn; ulong bandRow = 0, row, col; char mmuMode = true32b; OSErr theErr = noErr; LockPixels(dstPixMap); rowStart = (uchar *)GetPixBaseAddr(dstPixMap); ptr = dataStart; for (row = 0; row < 342; row++) { if (ptr < dataStart || ptr > dataEnd) { theErr = codecBadDataErr; break; } SwapMMUMode(&mmuMode); dst = rowStart; for (col = 0; col < 64; col++) *dst++ = *ptr++; SwapMMUMode(&mmuMode); rowStart += ((*dstPixMap)->rowBytes & 0x3fff); if (!(row & 63) && prog->progressProc) theErr = (OSErr)CallICMProgressProc(prog->progressProc, codecProgressUpdatePercent, FixRatio(row, 342), prog->progressRefCon); if (++bandRow == Height(&(*dstPixMap)->bounds)) { CopyPixMapToDestination(dstPixMap, row - bandRow + 1); bandRow = 0; rowStart = (uchar *)GetPixBaseAddr(dstPixMap); } if (theErr != noErr) break; } if (theErr == noErr && bandRow) CopyPixMapToDestination(dstPixMap, row - bandRow); SetPixelsState(dstPixMap, pState); return theErr; } //===================================================================================== // void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) //===================================================================================== // Copies the band contained in srcPixMap to the destination, offset from the top by // startRow. //===================================================================================== static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) { Rect srcRect = (*srcPixMap)->bounds, dstRect = (*srcPixMap)->bounds; PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); char srcState = HGetState((Handle)srcPixMap); char dstState = HGetState((Handle)dstPixMap); OffsetRect(&dstRect, 0, startRow); HLock((Handle)srcPixMap); HLock((Handle)dstPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &srcRect, &dstRect, srcCopy + ditherCopy, qd.thePort->visRgn); HSetState((Handle)dstPixMap, dstState); HSetState((Handle)srcPixMap, srcState); } \ No newline at end of file diff --git a/Source/C/SaveOpen.c b/Source/C/SaveOpen.c new file mode 100644 index 0000000..2642212 --- /dev/null +++ b/Source/C/SaveOpen.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif static OSErr MakePreviewAndIcons(Handle theHandle, ImageHandle theImage, Boolean preview, Boolean icons, NestedProgressPtr progProc, short cropWhat); static OSErr AddQuickTimePreview(FSSpec *theFile, GWorldPtr thePreview, Rect *theRect); static OSErr MakeIcons(FSSpec *theSpec, ImageHandle theImage); static OSErr MakeOneIcon(short theFile, OSType theType, GWorldPtr src, GWorldPtr dst, Rect *srcRect, Rect *dstRect); static void TrimIcon(Rect *theRect); static OSErr PixMapToHandle(PixMapHandle theMap, Rect *theRect, Rect *maskRect, Handle *theHandle); static Rect gPreviewRect, gIconRect; /* * DoSaveDocument(theImage, theSpec, theType, preview, palette) * * Purpose: Oversees the saving of a JPEG image file * Inputs: theImage = the image to be saved * theSpec = pointer to the destination file spec * theType = the destination type * preview = flag: true to create and save a preview image * palette = flag: true to save the palette with the image * Returns: an OSErr describing the result * */ OSErr DoSaveDocument(ImageHandle theImage, FSSpec *theSpec, OSType theType, Boolean preview, Boolean palette, Boolean icons, short cropWhat) { short total = (preview || icons) ? 1 : 0, i, theFile; NestedProgress theProc = { { nil, 0 }, 0, 0L, 0L }; FSSpec tempSpec, oldSpec = (*theImage)->file; Handle finalData = (*theImage)->data; ImageFormatPtr theAction = nil; OSErr theErr = noErr; // see if we can find the destination type in the type list for (i = 0; i < kFileFormats; i++) if (theType == gFormat[i]->outType) { if (((*theImage)->compression == kJPEGCompression && !gFormat[i]->fix) || ((*theImage)->compression != kJPEGCompression && gFormat[i]->save != (*theImage)->format->save)) continue; theAction = gFormat[i]; break; } if (!theAction) return errAETypeError; // ensure that we can actually save the current image in the requested format if (Banded(theImage) && !theAction->doesBanded) return errAETypeError; // adjust parameters to match the output format's limitations palette = palette && theAction->doesColors && (*theImage)->depth > 8; // initialize the progress proc, and open it right away theProc.prog.progressProc = gGenericProgress; theProc.prog.progressRefCon = (long)&theProc; UpdateParamText(gString[strPreparing], gNullString, gNullString, (*theImage)->file.name); CallICMProgressProc(theProc.prog.progressProc, codecProgressOpen, 0L, theProc.prog.progressRefCon); // determine the temporary file name (*theImage)->file = *theSpec; FSMakeFSSpec(theSpec->vRefNum, theSpec->parID, gString[strJPEGViewTempFile], &tempSpec); // if we want to save a palette, and we haven't calculated it yet, do it now if (palette && !(*theImage)->qpalette) { short depth = (*(*theImage)->dmon)->depth; PaletteHandle thePalette; if (depth < 4 || depth > 8) depth = 8; total++; theProc.end = 0x0000F000 / total; theErr = DoQuantize(theImage, 1L << depth, &thePalette, &theProc); theProc.prog.progressRefCon = (long)&theProc; if (theErr == noErr) (*theImage)->qpalette = thePalette; } if (theErr == noErr) { // update the progress, and do any internal JPEG conversions that are necessary theProc.begin = theProc.end; theProc.end += total ? (0x0000F000 / total) : 0L; KeepSpinning(); if ((*theImage)->compression == kJPEGCompression && theAction->fix) theErr = theAction->fix(theImage, &finalData, palette); // if everything's ok, create previews and icons if (theErr == noErr) theErr = MakePreviewAndIcons((*theImage)->data, theImage, preview, icons, &theProc, cropWhat); theProc.prog.progressRefCon = (long)&theProc; KeepSpinning(); // now, do the actual saving of the image if (theErr == noErr) UpdateParamText(gString[strSaving], gNullString, gNullString, (*theImage)->file.name); if (theErr == noErr) if (theAction->save) theErr = theAction->save(&tempSpec, finalData, preview ? gPreviewGWorld : nil, &gPreviewRect, (*theImage)->privateData); else theErr = DefaultSave(&tempSpec, finalData, nil, nil, theAction->outType); if (theErr == noErr && preview && !theAction->customPreviews) theErr = AddQuickTimePreview(&tempSpec, gPreviewGWorld, &gPreviewRect); KeepSpinning(); // if everything's still ok, we actually add the icons to the new file if (theErr == noErr && icons) { FSpCreateResFile(&tempSpec, kCreator, theType, 0); theErr = MakeIcons(&tempSpec, theImage); } // if things are still going well, we save the cropping rectangle as well if (theErr == noErr && (Cropped(theImage) || cropWhat == kCropImage)) { Rect **theRect = (Rect **)NewHandle(sizeof(Rect)); if (theRect) { if (cropWhat == kCropImage) SelRectToCropRect(theImage, *theRect); else **theRect = (*theImage)->crect; FSpCreateResFile(&tempSpec, kCreator, theType, 0); if (theFile = FSpOpenResFile(&tempSpec, fsRdWrPerm)) { AddResource((Handle)theRect, 'RECT', 0, gNullString); if ((theErr = ResError()) == noErr) WriteResource((Handle)theRect); else gIntError = errCantWriteFile; CloseResFile(theFile); } else theErr = ResError(), gIntError = errCantWriteFile; if (theErr != noErr) DisposeHandle((Handle)theRect); } else theErr = memFullErr, gIntError = errNoSaveMemory; } if (finalData && finalData != (*theImage)->data) DisposeHandle(finalData); KeepSpinning(); // finally, if nothing bad happened, exchange the temp file for the real file if (theErr == noErr) { theErr = FSpExchangeFiles(theSpec, &tempSpec); if (theErr == fnfErr) theErr = FSpRename(&tempSpec, theSpec->name); if (theErr == noErr) { FInfo theInfo; theErr = FSpGetFInfo(theSpec, &theInfo); if (theErr == noErr) { if (icons) theInfo.fdFlags |= kHasCustomIcon; theInfo.fdFlags &= ~kHasBeenInited; theInfo.fdCreator = kCreator; theInfo.fdType = theType; theErr = FSpSetFInfo(theSpec, &theInfo); } } } } // clean up and get outta here FSpDelete(&tempSpec); KeepSpinning(); ForceFolderUpdate(theSpec->parID, theSpec->vRefNum); theProc.end = 0x00010000; CallICMProgressProc(theProc.prog.progressProc, codecProgressClose, 0L, theProc.prog.progressRefCon); (*theImage)->file = oldSpec; return theErr; } extern OSErr DefaultSave(FSSpec *theSpec, Handle theHandle, GWorldPtr thePreview, Rect *theRect, OSType theType) { #if applec #pragma unused(thePreview, theRect) #endif long theSize = GetHandleSize(theHandle); char hState = HGetState(theHandle); short theFile; OSErr theErr; KeepSpinning(); theErr = FSpCreate(theSpec, kCreator, theType, 0); if (theErr == noErr) { KeepSpinning(); theErr = FSpOpenDF(theSpec, fsWrPerm, &theFile); if (theErr == noErr) { HLock(theHandle); SpinIndef(); theErr = FSWrite(theFile, &theSize, *theHandle); KeepSpinning(); if (theErr == noErr) { HSetState(theHandle, hState); if (theErr == noErr) { FSClose(theFile); return theErr; } } else gIntError = errCantWriteFile; HSetState(theHandle, hState); FSClose(theFile); } else gIntError = errCantOpenFile; FSpDelete(theSpec); } else gIntError = errCantCreateFile; return theErr; } static OSErr MakePreviewAndIcons(Handle theHandle, ImageHandle theImage, Boolean preview, Boolean icons, NestedProgressPtr progProc, short cropWhat) { #if applec #pragma unused(theHandle) #endif Rect prevSrcRect, iconSrcRect, prevDstRect, iconDstRect = { 0, 0, 32, 32 }, tmpRect; PixMapHandle dstPixMap = GetGWorldPixMap(gPreviewGWorld); short prevPort = -1, iconPort = -1; JVDrawParamsHandle theParams; StringPtr progressString; OSErr theErr = noErr; if (!preview && !icons) return noErr; // calculate the appropriate source/destination rectangles if (cropWhat != kCropImage) prevSrcRect = (*theImage)->crect; else SelRectToCropRect(theImage, &prevSrcRect); if (gThePrefs.iconStyle == isProportional || gThePrefs.iconStyle == isProportionalDog) { if (cropWhat == kCropNothing) iconSrcRect = (*theImage)->crect; else SelRectToCropRect(theImage, &iconSrcRect); MaxRect(&iconSrcRect, &gIconGWorld->portRect, &iconDstRect); } else { if (cropWhat == kCropNothing) MaxSquare(&prevSrcRect, &iconSrcRect); else { SelRectToCropRect(theImage, &tmpRect); MaxSquare(&tmpRect, &iconSrcRect); } } MaxRect(&prevSrcRect, &gPreviewGWorld->portRect, &prevDstRect); InsetRect(&iconDstRect, 1, 1); // set up the progress procedure if (preview && icons) progressString = gString[strCreatingPreviewIcons]; else if (preview) progressString = gString[strCreatingPreview]; else progressString = gString[strCreatingIcons]; UpdateParamText(progressString, gNullString, gNullString, (*theImage)->file.name); // allocate and initialize the drawing parameters tmpRect = (*theImage)->grect; if (theParams = NewDrawParams(&tmpRect, iqVHigh, false, progProc, (*theImage)->privateData)) { if (preview) SetUpDrawPort(theParams, kOffscreenPort1, gPreviewGWorld, &prevSrcRect, &prevDstRect, true); if (icons) SetUpDrawPort(theParams, preview ? kOffscreenPort2 : kOffscreenPort1, gIconGWorld, &iconSrcRect, &iconDstRect, true); // create the icons and preview KeepSpinning(); theErr = PreflightDrawing(theParams); PushPort(); if (theErr == noErr) { // lock down the pixels and erase the GWorlds LockPixels(GetGWorldPixMap(gPreviewGWorld)); MySetPort(gPreviewGWorld); ClipRect(&gPreviewGWorld->portRect); RGBForeColor(&gBlack); RGBBackColor(&gWhite); if (NeedsWhiteBG(theImage)) EraseRect(&gPreviewGWorld->portRect); else PaintRect(&gPreviewGWorld->portRect); LockPixels(GetGWorldPixMap(gIconGWorld)); MySetPort(gIconGWorld); ClipRect(&gPreviewGWorld->portRect); RGBForeColor(&gBlack); RGBBackColor(&gWhite); if (NeedsWhiteBG(theImage)) EraseRect(&gIconGWorld->portRect); else PaintRect(&gIconGWorld->portRect); // now get the ball rolling MySetPort((*theParams)->dummy); CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressOpen, 0L, (*theParams)->progress.prog.progressRefCon); // Either from the offscreen GWorld ... if ((*theImage)->gworld && GWOrigSize(theImage)) CopyGWorldToGWorld((*theImage)->gworld, (*theParams)->dummy, &(*theImage)->gworld->portRect, &(*theImage)->gworld->portRect, srcCopy, nil); // or from the image directly! else theErr = (*theImage)->format->draw((*theImage)->data, theParams); CallICMProgressProc((*theParams)->progress.prog.progressProc, codecProgressClose, 0L, (*theParams)->progress.prog.progressRefCon); UnlockPixels(GetGWorldPixMap(gPreviewGWorld)); UnlockPixels(GetGWorldPixMap(gIconGWorld)); KeepSpinning(); if (theErr == noErr) theErr = PostflightDrawing(theParams); else PostflightDrawing(theParams); } PopPort(); DisposeHandle((Handle)theParams); } gPreviewRect = prevDstRect; gIconRect = iconDstRect; return theErr; } /* * AddQuickTimePreview(theFile) * * Purpose: Adds the preview PICT to the newly-created PICT file * Inputs: theFile = pointer to a file spec * Returns: an OSErr describing what went wrong * */ static OSErr AddQuickTimePreview(FSSpec *theFile, GWorldPtr thePreview, Rect *theRect) { PixMapHandle dstPixMap = GetGWorldPixMap(thePreview); PicHandle previewData; short resRef; OSErr theErr; if (previewData = (PicHandle)NewHandle(4)) { KeepSpinning(); LockPixels(dstPixMap); theErr = MakeThumbnailFromPixMap(dstPixMap, theRect, 32, (PicHandle)previewData, (ICMProgressProcRecordPtr)&gDummyProg); UnlockPixels(dstPixMap); KeepSpinning(); if (theErr == noErr) { FSpCreateResFile(theFile, kCreator, kPICTType, 0); KeepSpinning(); if (resRef = FSpOpenResFile(theFile, fsRdWrPerm)) { KeepSpinning(); theErr = AddFilePreview(resRef, kPICTType, (Handle)previewData); KeepSpinning(); CloseResFile(resRef); } else gIntError = errCantWriteFile, theErr = fnfErr; } } else gIntError = errCantMakePreview, theErr = memFullErr; return theErr; } /* * MakeIcons(theSpec, theImage) * * Purpose: Handles the creation of icons for theImage * Inputs: theSpec = pointer to the destination file spec * theImage = handle to the image to make icons for * Returns: an OSErr describing the result * */ static OSErr MakeIcons(FSSpec *theSpec, ImageHandle theImage) { #if applec #pragma unused(theImage) #endif Rect bigRect = { 0, 0, 32, 32 }, smallRect = { 0, 0, 16, 16 }; OSErr theErr = noErr; GWorldPtr theGWorld; short theFile; if (!(theFile = FSpOpenResFile(theSpec, fsRdWrPerm))) return gIntError = errCantCreateIcons, ResError(); while (true) { if (!(theGWorld = MyNewGWorld(&bigRect, 8, nil, nil, true, false))) if (!(theGWorld = MyNewGWorld(&bigRect, 8, nil, nil, true, true))) { theErr = memFullErr; break; } theErr = MakeOneIcon(theFile, large8BitData, gIconGWorld, theGWorld, &gIconRect, &bigRect); if (theErr != noErr) break; theErr = MakeOneIcon(theFile, small8BitData, gIconGWorld, theGWorld, &gIconRect, &smallRect); if (theErr != noErr) break; DisposeGWorld(theGWorld); theGWorld = nil; if (!(theGWorld = MyNewGWorld(&bigRect, 4, nil, nil, true, false))) if (!(theGWorld = MyNewGWorld(&bigRect, 4, nil, nil, true, true))) { theErr = memFullErr; break; } theErr = MakeOneIcon(theFile, large4BitData, gIconGWorld, theGWorld, &gIconRect, &bigRect); if (theErr != noErr) break; theErr = MakeOneIcon(theFile, small4BitData, gIconGWorld, theGWorld, &gIconRect, &smallRect); if (theErr != noErr) break; DisposeGWorld(theGWorld); theGWorld = nil; if (!(theGWorld = MyNewGWorld(&bigRect, 1, nil, nil, true, false))) if (!(theGWorld = MyNewGWorld(&bigRect, 1, nil, nil, true, true))) { theErr = memFullErr; break; } theErr = MakeOneIcon(theFile, large1BitMask, gIconGWorld, theGWorld, &gIconRect, &bigRect); if (theErr != noErr) break; theErr = MakeOneIcon(theFile, small1BitMask, gIconGWorld, theGWorld, &gIconRect, &smallRect); break; } if (theGWorld) DisposeGWorld(theGWorld); if (theFile) CloseResFile(theFile); if (theErr != noErr) gIntError = errCantCreateIcons; return theErr; } /* * MakeOneIcon(theFile, theType, src, dst, srcRect, dstRect) * * Purpose: Creates and adds a single icon resource to theFile * Inputs: theFile = path number of the destination file's resource fork * theType = the type of icon to create * src = pointer to the source GWorld * dst = pointer to a properly-sized destination GWorld * srcRect = pointer to the source image's rectangle * dstRect = pointer to the destination icon's rectangle * Returns: an OSErr describing the result * */ static OSErr MakeOneIcon(short theFile, OSType theType, GWorldPtr src, GWorldPtr dst, Rect *srcRect, Rect *dstRect) { #if applec #pragma unused(theFile) #endif PixMapHandle srcMap = GetGWorldPixMap(src), dstMap = GetGWorldPixMap(dst); Rect realDstRect = *srcRect; Handle theHandle; short offset; OSErr theErr; MapRect(&realDstRect, &src->portRect, dstRect); if (Width(&realDstRect) < Height(&realDstRect)) { offset = (Height(&realDstRect) - Width(&realDstRect)) >> 1; realDstRect.left += offset; realDstRect.right += offset; } else { offset = (Width(&realDstRect) - Height(&realDstRect)) >> 1; realDstRect.top += offset; realDstRect.bottom += offset; } PushPort(); MySetPort(dst); HLock((Handle)srcMap); HLock((Handle)dstMap); LockPixels(srcMap); LockPixels(dstMap); EraseRect(dstRect); CopyBits((BitMap *)*srcMap, (BitMap *)*dstMap, srcRect, &realDstRect, srcCopy + ditherCopy, nil); UnlockPixels(srcMap); HUnlock((Handle)srcMap); TrimIcon(&realDstRect); if ((theErr = PixMapToHandle(dstMap, dstRect, &realDstRect, &theHandle)) != noErr) { PopPort(); return theErr; } UnlockPixels(dstMap); HUnlock((Handle)dstMap); PopPort(); AddResource(theHandle, theType, kCustomIconResource, gNullString); if ((theErr = ResError()) == noErr) { WriteResource(theHandle); KeepSpinning(); ReleaseResource(theHandle); return noErr; }; DisposeHandle(theHandle); return theErr; } /* * TrimIcon(theRect) * * Purpose: Trims the appropriate icon by folding over the upper-right corner * Inputs: theRect = pointer to the icon's rectangle * Returns: nothing * */ static void TrimIcon(Rect *theRect) { short offset = (Height(theRect) > 16 || Width(theRect) > 16) ? 6 : 4; Rect cornerRect; RGBForeColor(&gBlack); RGBBackColor(&gWhite); FrameRect(theRect); if (gThePrefs.iconStyle != isSquareDog && gThePrefs.iconStyle != isProportionalDog) return; MySetRect(&cornerRect, theRect->right - offset - 1, theRect->top, theRect->right, theRect->top + offset); EraseRect(&cornerRect); cornerRect.right--; MoveTo(cornerRect.left, cornerRect.top); LineTo(cornerRect.right, cornerRect.bottom); LineTo(cornerRect.left, cornerRect.bottom); LineTo(cornerRect.left, cornerRect.top); } /* * PixMapToHandle(theMap, theRect, theHandle) * * Purpose: Takes the icon image in theMap and makes an icon handle from it * Inputs: theMap = handle to the icon's pixmap * theRect = pointer to the icon's rectangle * theHandle = pointer to a place to receive the new handle * Returns: an OSErr describing the result * */ static OSErr PixMapToHandle(PixMapHandle theMap, Rect *theRect, Rect *maskRect, Handle *theHandle) { long theSize = (Height(theRect) * Width(theRect) * (*theMap)->pixelSize) >> 3; long r, c, words, rowBytes = (*theMap)->rowBytes & 0x3fff; char mode = true32b; ushort *s, *d; if ((*theMap)->pixelSize == 1) theSize <<= 1; if (*theHandle = NewHandle(theSize)) { words = (Width(theRect) * (*theMap)->pixelSize) >> 4; s = (ushort *)GetPixBaseAddr(theMap); d = (ushort *)StripAddress(**theHandle); SwapMMUMode(&mode); for (r = 0; r < Height(theRect); r++) { for (c = 0; c < words; c++) *d++ = s[c]; s += rowBytes >> 1; } SwapMMUMode(&mode); } else return memFullErr; if ((*theMap)->pixelSize == 1) { short offset = (Height(theRect) > 16 || Width(theRect) > 16) ? 6 : 4; Rect cornerRect; EraseRect(theRect); PaintRect(maskRect); if (gThePrefs.iconStyle == isSquareDog || gThePrefs.iconStyle == isProportionalDog) { MySetRect(&cornerRect, maskRect->right - offset - 1, maskRect->top, maskRect->right, maskRect->top + offset); EraseRect(&cornerRect); cornerRect.right--; MoveTo(cornerRect.left, cornerRect.top); LineTo(cornerRect.right, cornerRect.bottom); while (++cornerRect.top != cornerRect.bottom) { MoveTo(cornerRect.left, cornerRect.top); LineTo(cornerRect.left + cornerRect.top - maskRect->top, cornerRect.top); } } s = (ushort *)GetPixBaseAddr(theMap); SwapMMUMode(&mode); for (r = 0; r < Height(theRect); r++) { for (c = 0; c < words; c++) *d++ = s[c]; s += rowBytes >> 1; } SwapMMUMode(&mode); } return noErr; } /* * DoOpenDocument(theSpec, first) * * Purpose: Calls the appropriate routines to open an new image * Inputs: theSpec = the file specification for the new input file * first = flag: true if this is the first image in a series * Returns: an OSErr describing the result * */ OSErr DoOpenDocument(FSSpec *theFile, Boolean first, DescType openScreen, DescType openFull, Boolean autoExpand, Boolean openVisible, DescType openPalette, DescType drawQuality, Boolean openBitmaps, Boolean autoComments, Boolean fixTypes, Boolean fixCreator) { OSErr theErr = noErr; ImageHandle theImage; LMSetSFSaveDisk(-theFile->vRefNum); LMSetCurDirStore(theFile->parID); if (theImage = NewImage()) { (*theImage)->file = *theFile; if ((theErr = ReadFile(theImage, fixTypes, fixCreator)) == noErr) { if ((theErr = InitImage(theImage, openScreen, openFull, drawQuality, openVisible)) == noErr) { if ((theErr = MakeNewWindow(theImage, first, autoExpand)) == noErr) { MySetPort((CGrafPtr)(*theImage)->window); if (gSlideShow) SlideProgress(codecProgressRealOpen, 0, 0); AddWindowItem(theImage); if ((theErr = PickFirstPalette(theImage, openPalette)) == noErr) { if ((theErr = RenderOffscreen(theImage, openBitmaps)) == noErr) { if (gSlideShow) SlideProgress(codecProgressRealClose, 0, 0); if (openVisible) { if (!gSlideShow && first) ChangeActive((*theImage)->window); else FWShowWindow((*theImage)->window); if (autoComments && (*theImage)->comments && ((*theImage)->window == FWFrontWindow())) { if (OpenComments() == noErr) ChangeActive(GetCommentsWindow()); } SetStatistics(); AdjustMenus(); } return noErr; } } if (gSlideShow) SlideProgress(codecProgressRealClose, 0, 0); } else gIntError = errCantOpenWindow; } } } else gIntError = errNoLoadMemory, theErr = memFullErr; if ((theErr != codecAbortErr || gSlideShow) && theImage) { if ((*theImage)->window) DoCloseWindow((*theImage)->window, gThePrefs.restoreColors); else DisposeImage(theImage); } if (theErr == errBadJPEG) theErr = codecBadDataErr; return theErr; } /* * ReadFile(theImage) * * Purpose: Opens the input file, figures its type, and dispatches the read operation * to the appropriate routine * Inputs: theImage = the destination image record for the new image * Returns: an OSErr describing the problem * */ OSErr ReadFile(ImageHandle theImage, Boolean fixTypes, Boolean fixCreator) { FSSpec theSpec = (*theImage)->file; short theFile, theType; OSErr theErr = noErr; if (gGetAbout) { (*theImage)->format = &gPICTFormat; (*theImage)->data = GetResource(kPICTType, rAboutPict); if (!(*theImage)->data) theErr = ResError(); else DetachResource((*theImage)->data); (*theImage)->flags |= ifIsAboutBox; gGetAbout = false; return theErr; } if ((theErr = FSpOpenDF(&theSpec, fsRdPerm, &theFile)) != noErr) theFile = -1; if ((theType = IDImage(theFile, &theSpec)) != kInvalidType) { if (fixTypes) { FInfo theInfo; FSpGetFInfo(&theSpec, &theInfo); if (theInfo.fdType != gFormat[theType]->inType && theInfo.fdType != gFormat[theType]->altInType) { theInfo.fdType = gFormat[theType]->inType; if (fixCreator) theInfo.fdCreator = kCreator; FSpSetFInfo(&theSpec, &theInfo); FSClose(theFile); theErr = FSpOpenDF(&theSpec, fsRdPerm, &theFile); } } if (theErr == noErr) { (*theImage)->format = gFormat[theType]; if ((*theImage)->format->load) theErr = (*theImage)->format->load(theFile, theImage); else theErr = DefaultLoad(theFile, theImage); } } else { if (gIntError != errHSIFile) gIntError = errInvalidFile; theErr = errAETypeError; } if (theFile != -1) FSClose(theFile); return theErr; } //===================================================================================== // OSErr DefaultLoad(short theFile, ImageHandle theImage) //===================================================================================== // Performs a generic load of an image into memory, with no special processing. //===================================================================================== extern OSErr DefaultLoad(short theFile, ImageHandle theImage) { OSErr theErr = noErr; long theSize; KeepSpinning(); GetEOF(theFile, &theSize); if (!MakeMemAvailable(theSize)) return gIntError = errNoLoadMemory, memFullErr; if ((*theImage)->data = NewHandle(theSize)) { HLock((*theImage)->data); SpinIndef(); theErr = FSRead(theFile, &theSize, *(*theImage)->data); KeepSpinning(); HUnlock((*theImage)->data); if (theErr == noErr) return theErr; else DisposeHandle((*theImage)->data); gIntError = errCantReadFile; } else gIntError = errNoLoadMemory, theErr = memFullErr; return theErr; } /* * IDImage(theFile, theSpec) * * Purpose: Determines the image type by loading in a little and examining the header * Inputs: theFile = a pointer to the file number * theSpec = the original file specification * Returns: the index of the file type, or -1 if not a valid type * */ short IDImage(short theFile, FSSpec *theSpec) { uchar theBuffer[kHeaderSize + 64]; long theSize = kHeaderSize + 64; OSErr theErr = noErr; FInfo theInfo; short i; if (theFile != -1) { SetFPos(theFile, fsFromStart, 0); theErr = FSRead(theFile, &theSize, theBuffer); if (theErr != noErr && theErr != eofErr) theSize = 0; SetFPos(theFile, fsFromStart, 0); } else theSize = 0; if (FSpGetFInfo(theSpec, &theInfo) == noErr) { for (i = 0; i < kFileFormats; i++) if (gFormat[i]->id) { Boolean valid = gFormat[i]->id(theBuffer, theSize, theFile, theSpec); if (valid && (gFormat[i]->positiveID || gFormat[i]->inType == theInfo.fdType || gFormat[i]->altInType == theInfo.fdType)) return i; } } if (theBuffer[0] == 'h' && theBuffer[1] == 's' && theBuffer[2] == 'i' && theBuffer[3] == '1') gIntError = errHSIFile; /* #define errBinHexData 26 #define errUUEncodeData 27 */ return kInvalidType; } /* * InitImage(theImage, openScreen, openFull, drawQuality) * * Purpose: Initializes the fields in the image record * Inputs: theImage = the destination image record * openScreen = AE enum describing which screen to open up on * openFull = AE enum describing how to use full screen windows * drawQuality = AE enum describing the default drawing quality * visible = flag: true if the image is to be made visible * Returns: an OSErr describing what went wrong * */ OSErr InitImage(ImageHandle theImage, DescType openScreen, DescType openFull, DescType drawQuality, Boolean visible) { FSSpec theSpec = (*theImage)->file; short choice, refNum; OSErr theErr, AEErr; switch (openScreen) { case kAEOSDeepestColor: (*theImage)->dmon = GetDeepMonitor(true); break; case kAEOSDeepestGray: (*theImage)->dmon = GetDeepMonitor(false); break; case kAEOSLargestColor: (*theImage)->dmon = GetBigMonitor(true); break; case kAEOSLargestGray: (*theImage)->dmon = GetBigMonitor(false); break; case kAEOSMain: (*theImage)->dmon = gMainMonitor; break; } (*theImage)->smon = (*theImage)->dmon; theErr = (*theImage)->format->open(theImage); if (Height(&(*theImage)->grect) <= 0 || Width(&(*theImage)->grect) <= 0) gIntError = errCorruptImage, theErr = codecBadDataErr; if (theErr == errBadJPEG && (!gSlideShow || !(*gSlideOptions)->noErrors) && (gThePrefs.useQuickTime && gQTVersion)) { if (gInAppleEvent) { AEErr = AEInteractWithUser(kAEDefaultTimeout, &gTheNotification, gAEIdleProc); if (AEErr == errAENoUserInteraction) return codecBadDataErr; } StopSpinning(&qd.arrow); ParamText(gNullString, (*theImage)->file.name, gNullString, gNullString); choice = FWCautionAlert(CenterAlert(rBadJPEGAlert), gGenericFilter); if (choice == 3 || choice == kDialogCancel) return theErr; else gIntError = noErr, theErr = noErr; (*theImage)->flags |= ifCorrupt; StartSpinning(); } if (UseFullScreen(theImage, openFull, visible)) (*theImage)->flags |= ifFull; if (gSlideShow && (*gSlideOptions)->fileNames) (*theImage)->flags |= ifFilename; switch (drawQuality) { case kAEDQVeryHigh: (*theImage)->quality = iqVHigh; break; case kAEDQHigh: (*theImage)->quality = iqHigh; break; case kAEDQNormal: (*theImage)->quality = iqMedium; break; } if ((*theImage)->comments) { Size oldLength = GetHandleSize((*theImage)->comments), length = 0, i; uchar *src = (uchar *)*(*theImage)->comments, *dst = src; for (i = 0; i < oldLength; i++) if (*src >= 0x20) break; else src++; for ( ; i < oldLength; i++) if ((*src == 0x0d) || (*src >= 0x20)) *dst++ = *src++, length++; else src++; while ((length > 0) && (*--dst < 0x20)) length--; if (length > 0) SetHandleSize((*theImage)->comments, length); else DisposeHandle((*theImage)->comments), (*theImage)->comments = nil; } if (refNum = FSpOpenResFile(&theSpec, fsRdPerm)) { Rect **theRect; if (theRect = (Rect **)Get1Resource('RECT', 0)) { (*theImage)->crect = **theRect; (*theImage)->flags |= ifCropped; } CloseResFile(refNum); } return theErr; } /* * UseFullScreen(theImage, openFull, visible) * * Purpose: Determines whether the new image should be opened in full screen mode * Inputs: theImage = the image record for the image in question * openFull = AE enum describing how to use full screen windows * visible = flag: true if the image is to be made visible * Returns: nothing * */ Boolean UseFullScreen(ImageHandle theImage, DescType openFull, Boolean visible) { Rect screenRect, theRect; Boolean result; short choice; OSErr AEErr; if (openFull == kAEOFAlways) return true; else if (openFull == kAEOFNever) return false; GetActiveRect((*theImage)->dmon, &screenRect); screenRect.top += gTitleBarHeight; theRect = (*theImage)->crect; OffsetRect(&theRect, -theRect.left, -theRect.top); if (Width(&theRect) > Width(&screenRect)) theRect.bottom = (long)theRect.bottom * (long)Width(&screenRect) / (long)Width(&theRect); if (Height(&theRect) <= Height(&screenRect)) return false; if (openFull == kAEOFAlwaysIfLarge) return true; if (!visible) return false; if (gInAppleEvent) { AEErr = AEInteractWithUser(kAEDefaultTimeout, &gTheNotification, gAEIdleProc); if (AEErr == errAENoUserInteraction) return false; } StopSpinning(&qd.arrow); ParamText(gNullString, (*theImage)->file.name, gNullString, gNullString); choice = FWAlert(CenterAlert(rTooBigAlert), gGenericFilter); result = (choice == 1 || choice == kDialogOK); StartSpinning(); return result; } /* * PickFirstPalette(theImage, openPalette) * * Purpose: Determines which palette we should use for the given image * Inputs: theImage = the image record for the image in question * openFull = AE enum describing palette preferences * Returns: an OSErr describing what went wrong * */ OSErr PickFirstPalette(ImageHandle theImage, DescType openPalette) { short depth = (*(*theImage)->dmon)->depth; Boolean image = (*theImage)->ipalette && ((*(*theImage)->ipalette)->pmEntries <= (1L << depth)); Boolean quantize = ((*theImage)->depth >= 16); short palette = plNone; OSErr theErr = noErr; DescType thePalette; while (true) { if (!(*(*theImage)->dmon)->color && (depth <= 8)) { palette = plGrey; break; } else if (depth <= 2) { palette = plGrey; break; } else if (depth > 8) { palette = plSys; break; } switch (openPalette) { case kAEOPQuantImageScrn: case kAEOPQuantScrn: if (quantize) palette = plQuant; if ((openPalette != kAEOPQuantScrn) && image && (palette == plNone)) palette = plImage; if (palette == plNone) palette = plSys; break; case kAEOPImageQuantScrn: case kAEOPImageScrn: if (image) palette = plImage; if ((openPalette != kAEOPImageScrn) && quantize && (palette == plNone)) palette = plQuant; if (palette == plNone) palette = plSys; break; case kAEOPScrn: palette = plSys; break; } break; } switch (palette) { case plGrey: thePalette = kAEPGrayscale; break; case plImage: thePalette = kAEPImage; break; case plQuant: thePalette = kAEPQuantized; break; case plSys: default: thePalette = kAEPSystem; break; } if (!gThePrefs.ditherQuant && (palette == plQuant || (palette == plImage && (*theImage)->depth >= 16))) (*theImage)->flags &= ~ifDithered; else (*theImage)->flags |= ifDithered; if (theErr == noErr) theErr = DoSetPalette((*theImage)->window, thePalette); if (palette == plQuant && (*theImage)->npalette != plQuant) (*theImage)->flags |= ifDithered; if (theErr == codecAbortErr && !gSlideShow) { theErr = noErr; gIntError = 0; } return theErr; } /* * RenderOffscreen(theImage, openBitmaps) * * Purpose: Renders the given image into an offscreen buffer, if appropriate * Inputs: theImage = a pointer to the image in question * openBitmaps = flag: true if we should force an offscreen bitmap * Returns: an OSErr describing the problem, if any * */ OSErr RenderOffscreen(ImageHandle theImage, Boolean openBitmaps) { short flags = bfOffscreen + bfForceFull; OSErr theErr = noErr; ImageHandle image; Boolean itWorked; if ((*theImage)->gworld) return noErr; if (openBitmaps) { itWorked = MakeImageGWorld(theImage, false); if (!itWorked && gSlideShow) for (image = gImageRoot; image; image = (*image)->next) KillGWorld(image); if (itWorked || MakeImageGWorld(theImage, false)) { if (!gSlideShow) { ChangeActive((*theImage)->window); flags |= bfOnscreen; } if (!(flags & bfOnscreen) && gSlideShow) flags |= bfUseSlideProgress; SetSlideControlsText(gString[strSlideRendering], (*theImage)->file.name, gNullString, gNullString); theErr = DrawImage(theImage, flags, nil); } else if (!gSlideShow && ((*theImage)->compression || !gThePrefs.noUncomp)) gIntError = errNoOffscreenMemory, theErr = memFullErr; } return theErr; } \ No newline at end of file diff --git a/Source/C/SendAppleEvents.c b/Source/C/SendAppleEvents.c new file mode 100644 index 0000000..d2f9164 --- /dev/null +++ b/Source/C/SendAppleEvents.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "EventHandlers.h" //===================================================================================== // OSErr SendSetWindowBounds(WindowPtr theWindow, Rect *theRect) // // Sends a set data event to set the given window's global bounds. // // External calls: MakeWinPropertyObject, AEAddQDRectangle, HandleAEError //===================================================================================== extern OSErr SendSetWindowBounds(WindowPtr theWindow, Rect *theRect) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeWinPropertyObject(theWindow, pBounds, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddQDRectangle(&theEvent, keyAEData, theRect); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetWindowBounds(theWindow, theRect); HandleAEError(theErr, 0, nil); return theErr; } //===================================================================================== // OSErr SendSetZoomed(WindowPtr theWindow, Boolean zoomed) // // Sends a set data event to set the given window's zoomed flag. // // External calls: MakeWinPropertyObject, AEAddBoolean, HandleAEError //===================================================================================== extern OSErr SendSetZoomed(WindowPtr theWindow, Boolean zoomed) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeWinPropertyObject(theWindow, pIsZoomed, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddBoolean(&theEvent, keyAEData, &zoomed); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoZoomWindow(theWindow, zoomed); HandleAEError(theErr, 0, nil); return theErr; } /* * SendNewPalette(theImage, thePalette) * * Purpose: Sends ourself an AppleEvent to set an image's palette * Inputs: theImage = the image we're interested in * thePalette = constant describing the palette * Returns: nothing * */ OSErr SendNewPalette(ImageHandle theImage, DescType thePalette) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeDrawPropertyObject((*theImage)->window, pPalette, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) theErr = AEAddEnumerated(&theEvent, keyAEData, &thePalette); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetPalette((*theImage)->window, thePalette); HandleAEError(theErr, 0, nil); return theErr; } /* * SendDither(theImage) * * Purpose: Toggles the dither state of the current image * Inputs: theImage = the image we're interested in * Returns: nothing * */ OSErr SendDither(ImageHandle theImage, Boolean dither) { DescType theMode = dither ? kAEQDDitherCopy : kAEQDCopy; AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeDrawPropertyObject((*theImage)->window, pTransferMode, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddEnumerated(&theEvent, keyAEData, &theMode); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetImageDither(theImage, dither); HandleAEError(theErr, 0, nil); return theErr; } /* * SendQuality(theImage, theQuality) * * Purpose: Sets the quality of the current image * Inputs: theImage = the image we're interested in * Returns: nothing * */ OSErr SendQuality(ImageHandle theImage, DescType theQuality) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeDrawPropertyObject((*theImage)->window, pDrawQuality, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddEnumerated(&theEvent, keyAEData, &theQuality); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetImageQuality(theImage, theQuality); HandleAEError(theErr, 0, nil); return theErr; } /* * SendSetSelection(theImage, theRect) * * Purpose: Sends a set data event to the selection to set the selection for an image * Inputs: theImage = handle to the image of interest * theRect = pointer to the new selection rect * Returns: nothing * */ OSErr SendSetSelection(ImageHandle theImage, Rect *theRect) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeSelPropertyObject((*theImage)->window, pBounds, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddQDRectangle(&theEvent, keyAEData, theRect); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetSelection(theImage, theRect); HandleAEError(theErr, 0, nil); return theErr; } /* * SendCloneDocument(theImage, theNewImage) * * Purpose: Sends ourself an AppleEvent to clone a document and put the clone in * front of all other documents * Inputs: theImage = the image we're interested in * theNewImage = pointer to a location to store the new image's ImageHandle * Returns: nothing * */ OSErr SendCloneDocument(ImageHandle theImage, ImageHandle *theNewImage) { AEDesc theObject, theInsertionLoc, theReply, newObject; Boolean theBoolean = false; ObjectTokenHandle theToken; AppleEvent theEvent; OSErr theErr; *theNewImage = nil; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAEClone); if (theErr == noErr) { theErr = MakeWindowObject((*theImage)->window, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) theErr = AEAddBoolean(&theEvent, keyVisible, &theBoolean); if (theErr == noErr) theErr = AEMakeBeginningILoc(&theInsertionLoc, false); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyAEInsertHere, &theInsertionLoc); AEDisposeDesc(&theInsertionLoc); if (theErr == noErr) { theErr = AESend(&theEvent, &theReply, kAEWaitReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); if (theErr == noErr) { theErr = AEExtractObject(&theReply, keyAEResult, &newObject); if (theErr == noErr) { theToken = (ObjectTokenHandle)newObject.dataHandle; *theNewImage = FindImage((WindowPtr)(*theToken)->object[0]); } AEDisposeDesc(&theReply); } } } } AEDisposeDesc(&theEvent); } } else { WindowPtr newWindow; theErr = DoCloneWindow((*theImage)->window, nil, &newWindow); *theNewImage = FindImage(newWindow); } HandleAEError(theErr, 0, nil); return theErr; } /* * SendSetImageBounds(theImage, theRect) * * Purpose: Sets the bounds property of the given window's image * Inputs: theWindow = the window we're interested in * theRect = the new bounds * Returns: nothing * */ OSErr SendSetImageBounds(WindowPtr theWindow, Rect *theRect) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeImagePropertyObject(theWindow, pBounds, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddQDRectangle(&theEvent, keyAEData, theRect); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetImageBounds(FindImage(theWindow), theRect); HandleAEError(theErr, 0, nil); return theErr; } /* * SendSetWindowVis(theWindow, visible) * * Purpose: Sets the pIsVisible property of the given window * Inputs: theWindow = the window we're interested in * visible = flag: true to make the window visible * Returns: nothing * */ OSErr SendSetWindowVis(WindowPtr theWindow, Boolean visible) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeWinPropertyObject(theWindow, pVisible, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddBoolean(&theEvent, keyAEData, &visible); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetWindowVisible(theWindow, visible); HandleAEError(theErr, 0, nil); return theErr; } /* * SendOpenDocument(theSpec) * * Purpose: Sends the open document AppleEvent to ourself * Inputs: theSpec = pointer to the FSSpec record for the file * Returns: nothing * */ OSErr SendOpenDocument(FSSpec *theSpec) { AppleEvent theEvent; OSErr theErr; theErr = AENewEvent(&theEvent, kCoreEventClass, kAEOpenDocuments); if (theErr == noErr) { theErr = AEAddAliasList(&theEvent, keyDirectObject, theSpec, 1); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); AEDisposeDesc(&theEvent); } return theErr; } /* * SendCreateWindow(windowID) * * Purpose: Sends the create AppleEvent to ourself with a cWindow object * Inputs: windowID = ID value for the window to open * Returns: nothing * */ OSErr SendCreateWindow(DescType windowID) { AEDesc theInsertionLoc, theRecord; DescType theClass = cWindow; AppleEvent theEvent; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAECreateElement); if (theErr == noErr) { theErr = AEAddType(&theEvent, keyAEObjectClass, &theClass); if (theErr == noErr) theErr = AEMakeBeginningILoc(&theInsertionLoc, true); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyAEInsertHere, &theInsertionLoc); AEDisposeDesc(&theInsertionLoc); if (theErr == noErr) theErr = AECreateList(nil, 0, true, &theRecord); if (theErr == noErr) { theErr = AEPutKeyPtr(&theRecord, pWindowType, typeEnumerated, (void *)&windowID, sizeof(DescType)); if (theErr == noErr) AEPutParamDesc(&theEvent, keyAEPropData, &theRecord); AEDisposeDesc(&theRecord); if (theErr == noErr) { if ((windowID == kPrefsDialogID) || (windowID == kSlideShowDialogID)) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract,// + kAEDontRecord, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); else theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } } } AEDisposeDesc(&theEvent); } } else { WindowPtr dummyWindow; theErr = DoCreateWindow(windowID, nil, &dummyWindow); } HandleAEError(theErr, 0, nil); return theErr; } /* * SendCloseWindow(theWindow) * * Purpose: Sends the close AppleEvent to ourself with a cWindow object * Inputs: theWindow = pointer to the window, or kAEAll to close all windows * Returns: nothing * */ OSErr SendCloseWindow(WindowPtr theWindow) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAEClose); if (theErr == noErr) { if (theWindow == (WindowPtr)kAEAll) theErr = MakeDocumentObject(theWindow, &theObject); else theErr = MakeWindowObject(theWindow, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else { ImageHandle theImage, prevImage; if (theWindow == (WindowPtr)kAEAll) for (theImage = LastImage(); theImage; theImage = prevImage) { prevImage = PreviousImage(theImage); theErr = DoCloseWindow((*theImage)->window, gThePrefs.restoreColors); } else theErr = DoCloseWindow(theWindow, gThePrefs.restoreColors); } HandleAEError(theErr, 0, nil); return theErr; } /* * SendSaveDocument(theSpec, theFormat, preview, palette) * * Purpose: Sends the save AppleEvent to ourself with a cDocument object * Inputs: theSpec = pointer to the FSSpec record for the file * theFormat = the destination file format * preview = flag: true if we create and save a preview * palette = flag: true if we save the quantized palette * Returns: nothing * */ OSErr SendSaveDocument(FSSpec *theSpec, OSType theFormat, Boolean preview, Boolean palette, Boolean icons, short cropWhat) { OSErr theErr = noErr, intErr; AppleEvent theEvent; AEDesc theObject; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESave); if (theErr == noErr) { theErr = MakeDocumentObject((*FrontImage())->window, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) theErr = AEAddAlias(&theEvent, keyAEFile, theSpec); if (theErr == noErr) theErr = AEAddType(&theEvent, keyAEFileType, &theFormat); if (theErr == noErr) theErr = AEAddBoolean(&theEvent, keyCreatePreview, &preview); if (theErr == noErr) theErr = AEAddBoolean(&theEvent, keySaveQuant, &palette); if (theErr == noErr) theErr = AEAddBoolean(&theEvent, keyMakeIcons, &icons); if (theErr == noErr) theErr = AEAddShort(&theEvent, keyCropWhat, &cropWhat); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } intErr = (OSErr)gIntError; HandleAEError(theErr, errNoSaveMemory, theSpec->name); } else theErr = DoSaveDocument(FrontImage(), theSpec, theFormat, preview, palette, icons, cropWhat); return theErr; } /* * SendSlideShow() * * Purpose: Sends the slide show AppleEvent to ourself * Inputs: none * Returns: nothing * */ OSErr SendSlideShow(void) { Boolean askUser = true; AliasHandle theAlias; AppleEvent theEvent; AEDesc theDesc; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kJPEGViewSuite, kAESlideShow); if (theErr == noErr) { theErr = LoadPrefsHandle(kPrefsAliasType, 0, (Handle *)&theAlias); if (theErr == noErr) { theErr = AECreateHandleDesc(typeAlias, (Handle)theAlias, &theDesc); DisposeHandle((Handle)theAlias); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theDesc); AEDisposeDesc(&theDesc); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } } AEDisposeDesc(&theEvent); } } else theErr = DoSlideShow(); HandleAEError(theErr, 0, nil); return theErr; } /* * SendPrintDocument(theImage) * * Purpose: Sends the print document AppleEvent to ourself * Inputs: * Returns: nothing * */ OSErr SendPrintDocument(ImageHandle theImage) { AppleEvent theEvent; AEDesc theObject; Str63 theName; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kCoreEventClass, kAEPrintDocuments); if (theErr == noErr) { theErr = MakeDocumentObject((*theImage)->window, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } BlockMove((*theImage)->file.name, theName, *(*theImage)->file.name + 1); } else theErr = DoPrintDocument(theImage, true); HandleAEError(theErr, errNoPrintMemory, theName); return theErr; } /* * SendQuitApplication() * * Purpose: Sends the quit application AppleEvent to ourself * Inputs: none * Returns: nothing * */ OSErr SendQuitApplication(void) { AppleEvent theEvent, theReply; OSErr theErr; theErr = AENewEvent(&theEvent, kCoreEventClass, kAEQuitApplication); if (theErr == noErr) { theErr = AESend(&theEvent, &theReply, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); AEDisposeDesc(&theEvent); } HandleAEError(theErr, 0, nil); return theErr; } /* * SendSetFullScreen(theWindow, visible) * * Purpose: Sets the pFullScreen property of the given window * Inputs: theWindow = the window we're interested in * full = flag: true to make the window full screen * Returns: nothing * */ OSErr SendSetFullScreen(WindowPtr theWindow, Boolean full) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeWinPropertyObject(theWindow, pFullScreen, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddBoolean(&theEvent, keyAEData, &full); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetWindowFull(theWindow, full); HandleAEError(theErr, 0, nil); return theErr; } /* * SendSetDrawBounds(theImage, theRect) * * Purpose: Sets the bounds property of the given window's drawing area * Inputs: theWindow = the window we're interested in * theRect = the new bounds * Returns: nothing * */ OSErr SendSetDrawBounds(WindowPtr theWindow, Rect *theRect) { AppleEvent theEvent; AEDesc theObject; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAESetData); if (theErr == noErr) { theErr = MakeDrawPropertyObject(theWindow, pBounds, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) AEAddQDRectangle(&theEvent, keyAEData, theRect); if (theErr == noErr) theErr = AESend(&theEvent, nil, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); } AEDisposeDesc(&theEvent); } } else theErr = DoSetDrawBounds(FindImage(theWindow), theRect); HandleAEError(theErr, 0, nil); return theErr; } /* * SendMoveToFront(theWindow) * * Purpose: Sends ourself an AppleEvent to move the given window to the front * Inputs: theWindow = the window we're interested in * Returns: nothing * */ OSErr SendMoveToFront(WindowPtr theWindow) { AEDesc theObject, theInsertionLoc, theReply; AppleEvent theEvent; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAECoreSuite, kAEMove); if (theErr == noErr) { theErr = MakeWindowObject(theWindow, &theObject); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theObject); AEDisposeDesc(&theObject); if (theErr == noErr) theErr = AEMakeBeginningILoc(&theInsertionLoc, WindowKind(theWindow) == floatingWindowKind); if (theErr == noErr) { theErr = AEPutParamDesc(&theEvent, keyAEInsertHere, &theInsertionLoc); AEDisposeDesc(&theInsertionLoc); if (theErr == noErr) { theErr = AESend(&theEvent, &theReply, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); if (theErr != noErr) MinorError(errNoAESend); } else MinorError(errNoAESend); } else MinorError(errNoAESend); } else MinorError(errNoAESend); AEDisposeDesc(&theEvent); } else MinorError(errNoAESend); } else theErr = DoMoveWindow(theWindow, nil); return theErr; } /* * SendCopy() * * Purpose: Sends the copy AppleEvent to ourself * Inputs: none * Returns: nothing * */ OSErr SendCopy(void) { ImageHandle theImage = FrontImage(); AppleEvent theEvent, theReply; Str63 theName; OSErr theErr; if (gFoundOSL) { theErr = AENewEvent(&theEvent, kAEMiscStandards, kAECopy); if (theErr == noErr) { theErr = AESend(&theEvent, &theReply, kAENoReply + kAECanInteract, kAENormalPriority, kAEDefaultTimeout, gAEIdleProc, nil); AEDisposeDesc(&theEvent); } if (theImage) BlockMove((*theImage)->file.name, theName, *(*theImage)->file.name + 1); HandleAEError(theErr, errNoCopyMemory, theName); } else theErr = DoCopy(); return theErr; } \ No newline at end of file diff --git a/Source/C/SlideControlsWindow.c b/Source/C/SlideControlsWindow.c new file mode 100644 index 0000000..985ab78 --- /dev/null +++ b/Source/C/SlideControlsWindow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "SlideControlsWindow.h" //===================================================================================== // Global variables local to this module //===================================================================================== static short gButtonStatus[4] = { standard, standard, standard, standard }; static CIconHandle gStandardButton[4] = { nil, nil, nil, nil }; static CIconHandle gDepressedButton[4] = { nil, nil, nil, nil }; static CIconHandle gDisabledButton[4] = { nil, nil, nil, nil }; static WindowPtr gSlideControlsWindow = nil; static Str255 gSlideControlsText = "\p"; static Rect gButtonRect[4]; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr LoadButtons(void); //===================================================================================== // OSErr OpenSlideControls(void) // // Creates and initializes the slide show controls floating window. // // External calls: AllocateWindow, PushPort, MySetPort, GetActiveRect, PlaceWindow, // PopPort //===================================================================================== extern OSErr OpenSlideControls(void) { Rect theRect, mainRect; OSErr theErr = noErr; short width, height; FontInfo theInfo; Point where; short i; if (gSlideControlsWindow) return noErr; if (!gStandardButton[0]) theErr = LoadButtons(); if (!(gSlideControlsWindow = AllocateWindow())) theErr = memFullErr; if (theErr != noErr) return theErr; PushPort(); MySetPort(nil); if (gSlideControlsWindow = FWGetNewFloatingWindow(rSlideControlsWindow, (Ptr)gSlideControlsWindow, (WindowPtr)-1)) { MySetPort((CGrafPtr)gSlideControlsWindow); TextFont(geneva); TextSize(9); GetFontInfo(&theInfo); width = Width(&(*gStandardButton[0])->iconPMap.bounds); height = Height(&(*gStandardButton[0])->iconPMap.bounds); theRect.top = theRect.left = 0; theRect.right = width * 4; theRect.bottom = height + theInfo.ascent + theInfo.descent + theInfo.leading; SizeWindow(gSlideControlsWindow, Width(&theRect), Height(&theRect), true); GetActiveRect(gMainMonitor, &mainRect); where.h = mainRect.right - kWindowBorderWidth - Width(&theRect); where.v = mainRect.bottom - kWindowBorderHeight - Height(&theRect); PlaceWindow(gSlideControlsWindow, &gThePrefs.slideControlsBounds, where); for (i = 0; i < 4; i++) { gButtonRect[i].bottom = theRect.bottom; gButtonRect[i].top = theRect.bottom - height; gButtonRect[i].left = i * width; gButtonRect[i].right = i * width + width; } if (!*gSlideControlsText) SetSlideControlsText(gString[strSlideReady], gNullString, gNullString, gNullString); PopPort(); return noErr; } else theErr = memFullErr; CloseSlideControls(); PopPort(); return theErr; } //===================================================================================== // OSErr LoadButtons(void) // // Loads up the color icons used for buttons. // // External calls: none //===================================================================================== static OSErr LoadButtons(void) { short buttonType[4] = { rReverseButton, rStopButton, rPauseButton, rForwardButton }; short button; for (button = 0; button < 4; button++) { if (!(gStandardButton[button] = GetCIcon(buttonType[button] + rStandardButton)) || !(gDepressedButton[button] = GetCIcon(buttonType[button] + rDepressedButton)) || !(gDisabledButton[button] = GetCIcon(buttonType[button] + rDisabledButton))) return memFullErr; HLockHi((Handle)gStandardButton[button]); HLockHi((Handle)gDepressedButton[button]); HLockHi((Handle)gDisabledButton[button]); } return noErr; } //===================================================================================== // OSErr CloseSlideControls(void) // // Closes the slide show controls window. // // External calls: none //===================================================================================== extern void CloseSlideControls(void) { PushPort(); MySetPort(nil); if (gSlideControlsWindow) { SaveWindowPosition(gSlideControlsWindow, &gThePrefs.slideControlsBounds); FWCloseWindow(gSlideControlsWindow); DeallocateWindow(gSlideControlsWindow); } gSlideControlsWindow = nil; PopPort(); } //===================================================================================== // WindowPtr GetSlideControlsWindow(void) // // Returns a pointer to the slide show controls window. // // External calls: none //===================================================================================== extern WindowPtr GetSlideControlsWindow(void) { return gSlideControlsWindow; } //===================================================================================== // void SetSlideControlButton(short id, short status) // // Sets the status of a given control button. // // External calls: none //===================================================================================== extern void SetSlideControlButton(short id, short status) { gButtonStatus[id] = status; } //===================================================================================== // short GetSlideControlButton(short id) // // Returns the status of the given control button. // // External calls: none //===================================================================================== extern short GetSlideControlButton(short id) { return gButtonStatus[id]; } //===================================================================================== // void DrawSlideControlsWindow(void) // // Draws the contents of the slide show controls window. // // External calls: none //===================================================================================== extern void DrawSlideControlsWindow(void) { FontInfo theInfo; Rect theRect; short i; if (!gSlideControlsWindow) return; PushPort(); MySetPort((CGrafPtr)gSlideControlsWindow); theRect = gSlideControlsWindow->portRect; theRect.bottom = gButtonRect[0].top; TextFont(geneva); TextSize(9); GetFontInfo(&theInfo); MoveTo(2, theInfo.ascent + theInfo.leading); EraseRect(&theRect); TruncString(Width(&gSlideControlsWindow->portRect) - 4, gSlideControlsText, smTruncEnd); DrawString(gSlideControlsText); for (i = 0; i < 4; i++) { if (gButtonStatus[i] == depressed || gPendingButton == i) PlotCIcon(&gButtonRect[i], gDepressedButton[i]); else if (gButtonStatus[i] == standard) PlotCIcon(&gButtonRect[i], gStandardButton[i]); else PlotCIcon(&gButtonRect[i], gDisabledButton[i]); } PopPort(); } //===================================================================================== // void HandleSlideControlsClick(Point where, short modifiers, Boolean actNow) // // Draws the contents of the slide show controls window. // // External calls: none //===================================================================================== extern void HandleSlideControlsClick(Point where, short modifiers, Boolean actNow) { long startTime = TickCount(); Boolean isDepressed = false; short button, buttonFunction; gPendingButton = -1; PushPort(); MySetPort((CGrafPtr)gSlideControlsWindow); // convert to local coordinates, and look for a match to a button rectangle GlobalToLocal(&where); for (button = 0; button < 4; button++) if (gButtonStatus[button] == standard && PtInRect(where, &gButtonRect[button])) break; if (gSlideShow == kPaused && PtInRect(where, &gButtonRect[kPauseButton])) button = kPauseButton; // if we found one, track it until the mouse is released if (button < 4) { PlotCIcon(&gButtonRect[button], gDepressedButton[button]); isDepressed = true; while (StillDown()) { GetMouse(&where); if (PtInRect(where, &gButtonRect[button])) { if (!isDepressed) { PlotCIcon(&gButtonRect[button], gDepressedButton[button]); isDepressed = true; } } else if (isDepressed) { PlotCIcon(&gButtonRect[button], gStandardButton[button]); isDepressed = false; } } // if button was depressed when released, and we're allowed to act immediately, // do the appropriate action if (isDepressed) { buttonFunction = button; if ((modifiers & optionKey) && button == kPauseButton) buttonFunction = kHideButton; if (actNow && gSlideShow != kPaused) { while ((TickCount() - startTime) < 8); PlotCIcon(&gButtonRect[button], gStandardButton[button]); if ((*gSlideOptions)->userControl) gSlideShow = HandleUserControlButton(buttonFunction); else gSlideShow = HandleAutomaticButton(buttonFunction); if (!gSlideShow) CleanUpSlideShow(); } else gPendingButton = buttonFunction; } } PopPort(); if (HMIsBalloon()) HMRemoveBalloon(); } //===================================================================================== // void HandleSlideControlsKey(char theChar, short modifiers, Boolean actNow) // // Draws the contents of the slide show controls window. // // External calls: none //===================================================================================== extern void HandleSlideControlsKey(char theChar, short modifiers, Boolean actNow) { long startTime = TickCount(); short button, buttonFunction; gPendingButton = -1; // associate the keypress with one of the buttons if (theChar == kEscapeChar || (theChar == '.' && (modifiers & cmdKey))) button = kStopButton; else if (theChar == kLeftArrowChar) button = kReverseButton; else if (theChar == kUpArrowChar) button = kPauseButton; else button = kForwardButton; // if the button is disabled, beep if (gButtonStatus[button] == disabled) SysBeep(1); // otherwise, depress the button (if visible) else { PushPort(); if (gSlideControlsWindow) { MySetPort((CGrafPtr)gSlideControlsWindow); PlotCIcon(&gButtonRect[button], gDepressedButton[button]); } buttonFunction = button; if ((modifiers & optionKey) && button == kPauseButton) buttonFunction = kHideButton; // if we're to act now, dispatch the button to the appropriate handler if (actNow && gSlideShow != kPaused) { while ((TickCount() - startTime) < 8); if (gSlideControlsWindow) PlotCIcon(&gButtonRect[button], gStandardButton[button]); if ((*gSlideOptions)->userControl) gSlideShow = HandleUserControlButton(buttonFunction); else gSlideShow = HandleAutomaticButton(buttonFunction); if (!gSlideShow) CleanUpSlideShow(); } else gPendingButton = buttonFunction; PopPort(); } if (HMIsBalloon()) HMRemoveBalloon(); } //===================================================================================== // void Boolean HandleUserControlButton(short button) // // Handles button commands during a user-controlled slide show. // // External calls: none //===================================================================================== extern Boolean HandleUserControlButton(short button) { Boolean advance; switch (button) { case kStopButton: return false; case kPauseButton: gSlideShow = PauseSlideShow(&advance); return gSlideShow; case kHideButton: gSlideShow = HideSlideShow(&advance); return gSlideShow; case kReverseButton: PointToPreviousSlide(); case kForwardButton: do { advance = false; gSlideShow = NextSlide(&advance); if (gSlideShow) gSlideShow = LoadSlide(&advance); } while (advance && gSlideShow); return gSlideShow; } return true; } //===================================================================================== // Boolean HandleAutomaticButton(short button) // // Handles button commands during an automatic slide show. // // External calls: none //===================================================================================== extern Boolean HandleAutomaticButton(short button) { Boolean advance; switch (button) { case kStopButton: return false; case kPauseButton: gSlideShow = PauseSlideShow(&advance); return gSlideShow; case kHideButton: gSlideShow = HideSlideShow(&advance); return gSlideShow; case kReverseButton: PointToPreviousSlide(); case kForwardButton: do { advance = false; gSlideShow = NextSlide(&advance); if (gSlideShow) gSlideShow = LoadSlide(&advance); } while (advance && gSlideShow); return gSlideShow; } return true; } //===================================================================================== // Boolean PauseSlideShow(Boolean *advance) // // Oversees the pausing of the slide show. // // External calls: UnhideMenuBar, DispatchMainEvent, RehideMenuBar //===================================================================================== extern Boolean PauseSlideShow(Boolean *advance) { Boolean result, isNullEvent, isDialogEvent, wasHidden = false; short oldBackwardStatus = gButtonStatus[kReverseButton]; short oldForwardStatus = gButtonStatus[kForwardButton]; short oldPauseStatus = gButtonStatus[kPauseButton]; EventRecord theEvent; Str255 oldText; if (HMIsBalloon()) HMRemoveBalloon(); *advance = false; gSlideShow = kPaused; if (!gMenuVisible) UnhideMenuBar(); if (!gSlideControlsWindow && OpenSlideControls() == noErr) { ChangeActive(gSlideControlsWindow); wasHidden = true; } gButtonStatus[kPauseButton] = depressed; gButtonStatus[kForwardButton] = disabled; gButtonStatus[kReverseButton] = disabled; BlockMove(gSlideControlsText, oldText, *gSlideControlsText + 1); SetSlideControlsText(gString[strSlidePaused], gNullString, gNullString, gNullString); gPendingButton = -1; PushPort(); MySetPort((CGrafPtr)FWFrontWindow()); while (true) { isNullEvent = !WaitNextEvent(everyEvent - highLevelEventMask, &theEvent, kSleepTime, nil); isDialogEvent = FWIsDialogEvent(&theEvent); if (isNullEvent) { DialogPtr theDialog; short itemHit; theDialog = FWFrontWindow(); if (theDialog && WindowKind(theDialog) == dialogKind) FWDialogSelect(&theEvent, &theDialog, &itemHit); if (HMGetBalloons()) DispatchBalloonHelp(); } else DispatchMainEvent(&theEvent, isDialogEvent); if (gPendingButton != -1 || gDone) { short button = gPendingButton; gPendingButton = -1; if (button == kStopButton || gDone) { result = false; break; } else if (button == kPauseButton) { result = true; break; } } } if (GetSlideOptionsWindow()) CloseSlideOptions(); if (GetPrefsWindow()) ClosePrefs(); if (GetHelpWindow()) CloseHelp(); gSlideShow = kRunning; ChangeActive(FWFrontWindow()); BlockMove(oldText, gSlideControlsText, *oldText + 1); if (wasHidden && gSlideControlsWindow) CloseSlideControls(); gButtonStatus[kPauseButton] = oldPauseStatus; gButtonStatus[kForwardButton] = oldForwardStatus; gButtonStatus[kReverseButton] = oldBackwardStatus; DrawSlideControlsWindow(); PopPort(); return result; } //===================================================================================== // extern Boolean HideSlideShow(void) // // Hides the slide show by hiding all open windows, and then moving another process to // the front and pausing the slide show. // // External calls: //===================================================================================== extern Boolean HideSlideShow(Boolean *advance) { ProcessSerialNumber currentProcess = { 0, kCurrentProcess }; ProcessSerialNumber noProcess = { 0, kNoProcess }; ProcessSerialNumber newFrontProcess; ImageHandle theImage, frontImage; ProcessInfoRec theInfo; Boolean isSame, result; WindowPtr theWindow; OSErr theErr; // hide the slide background and all image windows; hide the front image last gHidden = true; if (theWindow = GetSlideBackWindow()) FWHideWindow(theWindow); frontImage = FrontImage(); for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if ((*theImage)->window && theImage != frontImage) FWHideWindow((*theImage)->window); if (frontImage) FWHideWindow((*frontImage)->window); ResetColors(); // move the process that launched us into the foreground; if we can't find it, // then move some other process to the front theInfo.processInfoLength = sizeof(ProcessInfoRec); theInfo.processName = nil; theInfo.processAppSpec = nil; theErr = GetProcessInformation(¤tProcess, &theInfo); if (theErr == noErr) { theErr = SameProcess(&noProcess, &theInfo.processLauncher, &isSame); if (!isSame) newFrontProcess = theInfo.processLauncher; else { newFrontProcess = noProcess; do { theErr = GetNextProcess(&newFrontProcess); theErr = SameProcess(¤tProcess, &newFrontProcess, &isSame); } while (isSame); } theErr = SetFrontProcess(&newFrontProcess); } // pause the slide show now result = PauseSlideShow(advance); return result; } //===================================================================================== // void SetSlideControlsText(StringPtr string0, StringPtr string1, StringPtr string2, // StringPtr string3) // // Sets the text of the slide show controls status. // // External calls: none //===================================================================================== extern void SetSlideControlsText(StringPtr string0, StringPtr string1, StringPtr string2, StringPtr string3) { Str255 newString; BlockMove(string0, newString, *string0 + 1); StuffString(newString, 1, string1); StuffString(newString, 2, string2); StuffString(newString, 3, string3); if (!EqualString(newString, gSlideControlsText, true, true)) { BlockMove(newString, gSlideControlsText, *newString + 1); if (gSlideControlsWindow) DrawSlideControlsWindow(); } } //===================================================================================== // void DoSlideControlsHelp(void) // // Handles balloon help in the slide controls floating window. // // External calls: none //===================================================================================== extern void DoSlideControlsHelp(Point globalPt) { Point tip = { 0, 0 }, localPt = globalPt; HMMessageRecord theRecord; short index = -1, i; Rect aRect; if (HMIsBalloon() || gInBackground) return; PushPort(); MySetPort((CGrafPtr)gSlideControlsWindow); GlobalToLocal(&localPt); if (localPt.v < gButtonRect[0].top) { index = 1; aRect = gSlideControlsWindow->portRect; aRect.bottom = gButtonRect[0].top; tip.h = aRect.right - 5; tip.v = aRect.bottom - 5; } else for (i = 0; i < 4; i++) { if (PtInRect(localPt, &gButtonRect[i])) { if (gButtonStatus[i] == standard) index = 2 + i; else if (gButtonStatus[i] == depressed) index = 6 + i; else if (gButtonStatus[i] == disabled) index = 10 + i; aRect = gButtonRect[i]; tip.h = aRect.right - 5; tip.v = aRect.bottom - 5; } } if (index && HMExtractHelpMsg(kHMRectListResType, rSlideControlsWindow, index, kHMEnabledItem, &theRecord) == noErr) { LocalToGlobal(&tip); GlobalRect(&aRect, gSlideControlsWindow); HMShowBalloon(&theRecord, tip, &aRect, nil, 0, 0, kHMRegularWindow); } PopPort(); } \ No newline at end of file diff --git a/Source/C/SlideShow.c b/Source/C/SlideShow.c new file mode 100644 index 0000000..a8c4df1 --- /dev/null +++ b/Source/C/SlideShow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "SlideShow.h" //===================================================================================== // Constants local to this module //===================================================================================== enum { kEndSlideShow = -1, kAdvanceSlide = -2, kReloadSlide = -3, kReverseSlide = -4 }; //===================================================================================== // Global variables local to this module //===================================================================================== static Boolean gSlideWarned = false, gStatsHidden, gColorsHidden, gCommentsHidden; static ImageHandle gSlideNextImage = nil; static WindowPtr gSlideBackWindow = nil; static SlideHandle gSlideNext = nil; static SlideHandle gSlideRoot = nil; static long gSlideTimer = 0L; static long gSlideCount = 0L; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static void OpenSlideBackWindow(void); static SlideHandle NewSlide(Boolean memory, FSSpec *spec); static void DisposeSlide(SlideHandle theSlide); static SlideHandle LastSlide(void); static SlideHandle PreviousSlide(SlideHandle theSlide); static SlideHandle DisplayedSlide(void); static void ShuffleSlides(void); static ImageHandle LoadSlideFromMem(void); static ImageHandle LoadSlideFromDisk(void); static ImageHandle HandleLoadError(OSErr theErr, StringPtr fileName); static Boolean WarnSlideShowMemory(void); //===================================================================================== // void OpenSlideBackWindow(void) // // Creates and displays the background window for the slide show. // // External calls: GetDeepMonitor, PushPort, MySetPort, FullScreen, PopPort //===================================================================================== static void OpenSlideBackWindow(void) { MonitorHandle deepMonitor; PaletteHandle thePalette; deepMonitor = GetDeepMonitor(true); thePalette = SystemPalette((*deepMonitor)->depth <= 8 ? (*deepMonitor)->depth : 8); PushPort(); MySetPort(nil); FullScreen(gMainMonitor); gSlideBackWindow = FWGetNewCWindow(rFullImageWindow, (Ptr)gSlideBackWindow, (WindowPtr)-1); SizeWindow(gSlideBackWindow, Width(&(*GetGrayRgn())->rgnBBox), Height(&(*GetGrayRgn())->rgnBBox), true); FWMoveWindow(gSlideBackWindow, (*GetGrayRgn())->rgnBBox.left, (*GetGrayRgn())->rgnBBox.top, true); SetPalette(gSlideBackWindow, thePalette, true); ActivatePalette(gSlideBackWindow); MySetPort((CGrafPtr)gSlideBackWindow); SetOrigin((*GetGrayRgn())->rgnBBox.left, (*GetGrayRgn())->rgnBBox.top); FWShowWindow(gSlideBackWindow); DrawSlideBackWindow(); PopPort(); } //===================================================================================== // WindowPtr GetSlideBackWindow(void) // // Returns a pointer to the slide backdrop window. // // External calls: GetDeepMonitor, PushPort, MySetPort, FullScreen, PopPort //===================================================================================== extern WindowPtr GetSlideBackWindow(void) { return gSlideBackWindow; } //===================================================================================== // void CloseSlideBackWindow(void) // // Closes the slide backdrop window. // // External calls: none //===================================================================================== extern void CloseSlideBackWindow(void) { if (gSlideBackWindow) { PushPort(); MySetPort(nil); FWDisposeWindow(gSlideBackWindow); DeallocateWindow(gSlideBackWindow); gSlideBackWindow = nil; if (!AnotherFull(nil)) NormalScreen(gMainMonitor); PopPort(); } } //===================================================================================== // void DrawSlideBackWindow(void) // // Draws a JPEGView icon in the center of each screen. // // External calls: none //===================================================================================== extern void DrawSlideBackWindow(void) { MonitorHandle theMonitor; Rect theRect; for (theMonitor = gMainMonitor; theMonitor; theMonitor = (*theMonitor)->next) { theRect = (*theMonitor)->rect; theRect.left += (Width(&theRect) - 32) / 2; theRect.top += (Height(&theRect) - 32) / 2; theRect.right = theRect.left + 32; theRect.bottom = theRect.top + 32; PlotIconSuite(&theRect, atAbsoluteCenter, ttNone, gIconSuite); } } //===================================================================================== // void ResetSlideTimer(void) // // Resets the slide timer, maintained by HandleSlideNullEvent. // // External calls: none //===================================================================================== extern void ResetSlideTimer(void) { gSlideTimer = TickCount(); } //===================================================================================== // void HandleSlideNullEvent(void) // // Handles null events while a slide show is active. // // External calls: none //===================================================================================== extern void HandleSlideNullEvent(void) { ulong newCount = TickCount(); EvQElPtr theEvent; Boolean advance; // if we're in screen saver mode, make sure the mouse didn't move if (gScreenSaver) { Point newMouse = GlobalMouse(); if (abs(newMouse.h - gScreenSaverPoint.h) > 2 || abs(newMouse.v - gScreenSaverPoint.v) > 2) { SendQuitApplication(); return; } } // if we're automatic, enable the play button here if (!(*gSlideOptions)->userControl && GetSlideControlButton(kForwardButton) == disabled) { SetSlideControlButton(kForwardButton, standard); DrawSlideControlsWindow(); } // if the slide show is paused, don't do this bit if (gSlideShow == kPaused) return; if ((*gSlideOptions)->userControl) SetSlideControlsText(gString[strSlideReady], gNullString, gNullString, gNullString); // if the timer isn't up yet, and we're in the foreground, post a fake // key down event to prevent screen savers from kicking in else if (((newCount - gSlideTimer) / kClockFreq) <= (*gSlideOptions)->delay && !gInBackground) { Str32 theCount; PPostEvent(keyDown, kCreator, &theEvent); NumToString((*gSlideOptions)->delay - (newCount - gSlideTimer) / kClockFreq, theCount); SetSlideControlsText(gString[strSlideDelaying], theCount, gNullString, gNullString); return; } // if we're under user control, or if we're paused if ((*gSlideOptions)->userControl || gSlideShow == kPaused) return; // otherwise, reset the slide timer, draw this slide and then start loading the next gSlideTimer = newCount; do { advance = false; gSlideShow = NextSlide(&advance); if (gSlideShow) gSlideShow = LoadSlide(&advance); } while (advance && gSlideShow); } //===================================================================================== // SlideHandle NewSlide(Boolean memory, FSSpec *spec) // // Creates a new slide handle and appends it to the beginning of the linked list. // // External calls: none //===================================================================================== static SlideHandle NewSlide(Boolean memory, FSSpec *spec) { long theSize = sizeof(SlideItem); SlideHandle theSlide; if (!IsMemAvailable(sizeof(SlideItem))) return nil; if (gSlideRoot) { for (theSlide = gSlideRoot; (*theSlide)->next; theSlide = (*theSlide)->next); theSlide = (*theSlide)->next = (SlideHandle)NewHandle(sizeof(SlideItem)); } else theSlide = gSlideRoot = (SlideHandle)NewHandle(sizeof(SlideItem)); if (theSlide) { (*theSlide)->next = nil; (*theSlide)->mem = memory; (*theSlide)->spec = *spec; gSlideCount++; } return theSlide; } //===================================================================================== // void DisposeSlide(SlideHandle theSlide) // // Removes a slide handle from the linked list. // // External calls: none //===================================================================================== static void DisposeSlide(SlideHandle theSlide) { Boolean found = false; SlideHandle tempSlide; if (theSlide != gSlideRoot) { for (tempSlide = gSlideRoot; tempSlide && ((*tempSlide)->next != theSlide); tempSlide = (*tempSlide)->next); if (tempSlide) (*tempSlide)->next = (*theSlide)->next; } else gSlideRoot = (*gSlideRoot)->next; DisposeHandle((Handle)theSlide); gSlideCount--; } //===================================================================================== // SlideHandle PreviousSlide(SlideHandle theSlide) // // Returns the slide in the list previous to the given slide. // // External calls: none //===================================================================================== static SlideHandle LastSlide(void) { SlideHandle theSlide; if (!gSlideRoot) return nil; for (theSlide = gSlideRoot; (*theSlide)->next; theSlide = (*theSlide)->next); return theSlide; } static SlideHandle PreviousSlide(SlideHandle theSlide) { SlideHandle slide; if (!theSlide || theSlide == gSlideRoot || theSlide == (SlideHandle)kEndSlideShow) return LastSlide(); for (slide = gSlideRoot; slide; slide = (*slide)->next) if ((*slide)->next == theSlide) return slide; return nil; } static SlideHandle DisplayedSlide(void) { SlideHandle theSlide = PreviousSlide(gSlideNext); ImageHandle theImage = FrontImage(); short imageIndex; if (!theImage) return nil; imageIndex = GetDocumentIndex((*theImage)->window); do { if ((*theSlide)->mem) { if ((*theSlide)->spec.vRefNum == imageIndex) return theSlide; } else if (SameFile(&(*theImage)->file, &(*theSlide)->spec)) return theSlide; theSlide = PreviousSlide(theSlide); } while (theSlide != gSlideNext); return nil; } //===================================================================================== // void PointToPreviousSlide(void) // // Backs up the gSlideNext pointer by the specified count. // // External calls: none //===================================================================================== extern void PointToPreviousSlide(void) { SlideHandle currentSlide = DisplayedSlide(); ImageHandle frontImage = FrontImage(); if (currentSlide) { if ((*currentSlide)->next == gSlideNext || (*(*currentSlide)->next)->next == gSlideNext) gSlideNext = PreviousSlide(currentSlide); else if (gSlideNext != gSlideRoot) gSlideNext = PreviousSlide(gSlideNext); else SysBeep(1); } else SysBeep(1); if (gSlideNextImage && gSlideNextImage != frontImage) DoCloseWindow((*gSlideNextImage)->window, false); gSlideNextImage = nil; } //===================================================================================== // void InitSlideShow(void) // // Initializes a new slide show; does not properly set up for a resumed slide show. // // External calls: none //===================================================================================== extern void InitSlideShow(void) { ImageHandle theImage; WindowPtr theWindow; Boolean advance; FSSpec theSpec; gSlideShow = false; // if we're doing a memory-based slide show, generate the slide entries here if (!gSlideRoot && (*gSlideOptions)->fromMemory) for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) { theSpec.vRefNum = GetDocumentIndex((*theImage)->window); NewSlide(true, &theSpec); } // if for some reason we have no slides, signal the error and return if (!gSlideCount) { MinorError(errNoImagesFound); MyInvalMenuBar(); return; } // if we are to hide the floating windows, do it now gStatsHidden = gCommentsHidden = gColorsHidden = false; if ((*gSlideOptions)->hideWindoids) { if (theWindow = GetStatWindow()) gStatsHidden = true, CloseStats(); if (theWindow = GetCommentsWindow()) gCommentsHidden = true, CloseComments(); if (theWindow = GetColorsWindow()) gColorsHidden = true, CloseColors(); } // if the slide background window has not been opened, we allocate and open it now if (!gSlideBackWindow && (gSlideBackWindow = AllocateWindow())) OpenSlideBackWindow(); // set up the slide control buttons ahead of time here SetSlideControlButton(kReverseButton, disabled); SetSlideControlButton(kStopButton, standard); SetSlideControlButton(kPauseButton, standard); SetSlideControlButton(kForwardButton, standard); // if this is user-controlled, pop up the controls window now if (!(*gSlideOptions)->hideControls && OpenSlideControls() == noErr) ChangeActive(GetSlideControlsWindow()); // if this is a disk-based slide show, close all other open images if (!(*gSlideOptions)->fromMemory) while (gImageRoot) DoCloseWindow((*LastImage())->window, false); // reset all the appropriate variables, then load, draw, and load the second slide if ((*gSlideOptions)->random) ShuffleSlides(); gSlideNextImage = nil; gSlideWarned = false; gSlideNext = gSlideRoot; gSlideShow = true; advance = false; if (gSlideShow = LoadSlide(&advance)) { do { advance = false; gSlideShow = NextSlide(&advance); if (gSlideShow) gSlideShow = LoadSlide(&advance); } while (advance && gSlideShow); } // if we got shoved in the background, start in the paused state if (gInBackground && !gScreenSaver) { Boolean dummy; gSlideShow = PauseSlideShow(&dummy); } } //===================================================================================== // void ReinitSlideShow(PrefsData *oldPrefs) // // Initializes a new slide show; does not properly set up for a resumed slide show. // // External calls: none //===================================================================================== extern void ReinitSlideShow(SlideOptionsPtr oldOptions) { WindowPtr theWindow; if (oldOptions->hideWindoids != (*gSlideOptions)->hideWindoids) { if ((*gSlideOptions)->hideWindoids) { if (theWindow = GetStatWindow()) gStatsHidden = true, CloseStats(); if (theWindow = GetCommentsWindow()) gCommentsHidden = true, CloseComments(); if (theWindow = GetColorsWindow()) gColorsHidden = true, CloseColors(); } else { if (gStatsHidden && OpenStats() == noErr) ChangeActive(GetStatWindow()); if (gCommentsHidden && OpenComments() == noErr) ChangeActive(GetCommentsWindow()); if (gColorsHidden && OpenColors() == noErr) ChangeActive(GetColorsWindow()); } } if (oldOptions->hideControls != (*gSlideOptions)->hideControls) { if (!(*gSlideOptions)->hideControls && OpenSlideControls() == noErr) ChangeActive(GetSlideControlsWindow()); else if ((*gSlideOptions)->hideControls && GetSlideControlsWindow()) CloseSlideControls(); } gPendingButton = kForwardButton; } //===================================================================================== // void AddSlideDir(FSSpec *spec) // // Adds a given file or directory to the list of slides to be displayed, recognizing // the request for recursive directory scans. // // External calls: none //===================================================================================== extern OSErr AddSlideDir(FSSpec *spec, Boolean recursive, ICMProgressProcRecordPtr theProg, LoopCheckPtr loopList) { FSSpec dirSpec = *spec, theSpec; Boolean isFolder, wasAliased; OSErr theErr = noErr; LoopCheck thisDir; CInfoPBRec block; Str255 fileName; long dir; if (ResolveAliasFile(&dirSpec, true, &isFolder, &wasAliased) != noErr) return noErr; if (isFolder) { theErr = GetDirectoryID(&dirSpec, &dir); if (theErr != noErr) return noErr; thisDir.prev = loopList; thisDir.vRefNum = dirSpec.vRefNum; thisDir.dirID = dir; while (loopList) { if (loopList->vRefNum == dirSpec.vRefNum && loopList->dirID == dir) return noErr; loopList = loopList->prev; } UpdateParamText(gString[strScanningDirectory], gNullString, gNullString, spec->name); } else { if (!NewSlide(false, &dirSpec)) return memFullErr; return noErr; } block.hFileInfo.ioNamePtr = fileName; block.hFileInfo.ioFDirIndex = 1; block.hFileInfo.ioVRefNum = dirSpec.vRefNum; block.hFileInfo.ioDirID = dir; if (theProg && (OSErr)CallICMProgressProc(theProg->progressProc, codecProgressUpdatePercent, kIndefProgress, theProg->progressRefCon) == codecAbortErr) return codecAbortErr; while (PBGetCatInfo(&block, false) == noErr && theErr == noErr) { KeepSpinning(); FSMakeFSSpec(dirSpec.vRefNum, dir, fileName, &theSpec); if (ResolveAliasFile(&theSpec, true, &isFolder, &wasAliased) == noErr) { if (isFolder) { if (recursive) { theErr = AddSlideDir(&theSpec, (*gSlideOptions)->recursive, theProg, &thisDir); if (theErr != noErr) break; } } else if ((*gSlideOptions)->allFiles) { short theFile, fileType; if (FSpOpenDF(&theSpec, fsRdPerm, &theFile) == noErr) { fileType = IDImage(theFile, &theSpec); FSClose(theFile); if (fileType != kInvalidType) if (!NewSlide(false, &theSpec)) { theErr = memFullErr; break; } } } else if (ValidType(block.hFileInfo.ioFlFndrInfo.fdType)) if (!NewSlide(false, &theSpec)) { theErr = memFullErr; break; } if (!(block.hFileInfo.ioFDirIndex & 0x0f)) if (theProg && (OSErr)CallICMProgressProc(theProg->progressProc, codecProgressUpdatePercent, kIndefProgress, theProg->progressRefCon) == codecAbortErr) return codecAbortErr; } block.hFileInfo.ioFDirIndex++; block.hFileInfo.ioDirID = dir; } return theErr; } //===================================================================================== // void CleanUpSlideShow(void) // // Cleans up for when the slide show is completely finished. // // External calls: none //===================================================================================== extern void CleanUpSlideShow(void) { ImageHandle theImage, nextImage; short choice = 0; while (gSlideRoot) DisposeSlide(gSlideRoot); if (GetSlideControlsWindow()) CloseSlideControls(); if (GetSlideBackWindow()) CloseSlideBackWindow(); gSlideShow = false; if (!(*gSlideOptions)->fromMemory) for (theImage = gImageRoot; theImage; theImage = nextImage) { nextImage = (*theImage)->next; if (theImage != FrontImage()) DoCloseWindow((*theImage)->window, gThePrefs.restoreColors); } if ((*gSlideOptions)->hideWindoids) { if (gStatsHidden && OpenStats() == noErr) ChangeActive(GetStatWindow()); if (gCommentsHidden && OpenComments() == noErr) ChangeActive(GetCommentsWindow()); if (gColorsHidden && OpenColors() == noErr) ChangeActive(GetColorsWindow()); } for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if (GWTempMem(theImage)) KillGWorld(theImage); EnableMenus(); if (theImage = FrontImage()) (*theImage)->flags &= ~ifAborted; } //===================================================================================== // void ShuffleSlides(void) // // Shuffles the linked list of slides in a pseudo-random order. // // External calls: none //===================================================================================== static void ShuffleSlides(void) { SlideHandle theSlide, tempSlide; long i, j, k; for (i = 0; i < (gSlideCount * 4); i++) { j = ((ushort)Random()) % gSlideCount; if (j > 0) { for (theSlide = gSlideRoot, k = 1; (k < j) && theSlide; k++) theSlide = (*theSlide)->next; if (theSlide) { tempSlide = (*theSlide)->next; (*theSlide)->next = (*tempSlide)->next; (*tempSlide)->next = gSlideRoot; gSlideRoot = tempSlide; } } } } //===================================================================================== // void LoadSlide(void) // // Loads the next slide, skipping over any that cause errors. // // External calls: none //===================================================================================== extern Boolean LoadSlide(Boolean *advance) { SlideHandle theSlide; // loop until we get a good slide while (!gSlideNextImage) { if (!(*gSlideOptions)->userControl) ObscureCursor(); // enable the reverse button if we're not loading the first two slides if (gSlideNext != gSlideRoot && (theSlide = DisplayedSlide()) && theSlide != gSlideRoot) SetSlideControlButton(kReverseButton, standard); else SetSlideControlButton(kReverseButton, disabled); // load the next slide, either from memory, or from disk if ((*gSlideNext)->mem) gSlideNextImage = LoadSlideFromMem(); else gSlideNextImage = LoadSlideFromDisk(); // if we've ended the show, clean up and return false if (gSlideNextImage == (ImageHandle)kEndSlideShow) { CleanUpSlideShow(); return false; // if we're supposed to advance forward one, set the flag } else if (gSlideNextImage == (ImageHandle)kAdvanceSlide) { gSlideNextImage = nil; *advance = true; } // if we're supposed to reload the current slide, skip this next part if (gSlideNextImage == (ImageHandle)kReloadSlide) { gSlideNextImage = nil; *advance = true; // if we're backing up, back gSlideNext up one and reload, skipping next } else if (gSlideNextImage == (ImageHandle)kReverseSlide) { gSlideNextImage = nil; PointToPreviousSlide(); *advance = true; // save the handle to the current slide, and find the next one, restarting // and reshuffling as appropriate } else { theSlide = gSlideNext; if (!(gSlideNext = (*gSlideNext)->next)) { if (!(*gSlideOptions)->repeat) { if (gSlideNextImage) { gSlideNext = (SlideHandle)kEndSlideShow; return true; } else { EndSlideShow(); CleanUpSlideShow(); return false; } } else { if ((*gSlideOptions)->random) ShuffleSlides(); gSlideNext = gSlideRoot; } } // if we got an unprocessed forward arrow, set the advance flag if (gPendingButton == kForwardButton) { *advance = true; gPendingButton = -1; } // if there was an error in setting up the last slide, kill it from the list if (!gSlideNextImage) { if (gSlideNext == theSlide) { gSlideNext = (*gSlideNext)->next; if (!gSlideNext && gSlideRoot == theSlide) { CleanUpSlideShow(); EndSlideShow(); return false; } else if (!gSlideNext) gSlideNext = gSlideRoot; } DisposeSlide(theSlide); } } } return true; } //===================================================================================== // ImageHandle LoadSlideFromMem(void) // // Sets up the next slide for an in-memory slide show. // // External calls: FindImage, IndexedDocument, DoSetWindowFull //===================================================================================== static ImageHandle LoadSlideFromMem(void) { ImageHandle theImage; OSErr theErr = noErr; theImage = FindImage(IndexedDocument((*gSlideNext)->spec.vRefNum)); if (!Full(theImage)) theErr = DoSetWindowFull((*theImage)->window, true); if (theErr == noErr) return theImage; if (!(*gSlideOptions)->noErrors) HandleAEError(theErr, errNoDrawMemory, (*theImage)->file.name); return nil; } //===================================================================================== // ImageHandle LoadSlideFromDisk(SlideHandle theSlide) // // Sets up the next slide for a disk-based slide show; returns nil if the image failed // to load; returns (ImageHandle)-1 if the slide show should end. // // External calls: GetOpenDefaults, DoOpenDocument, StopSpinning, HandleAEError //===================================================================================== static ImageHandle LoadSlideFromDisk(void) { DescType openScreen, openFull, openPalette, drawQuality; FSSpec theSpec = (*gSlideNext)->spec; ImageHandle theImage; OSErr theErr; do { SetSlideControlsText(gString[strSlideLoading], theSpec.name, gNullString, gNullString); GetOpenDefaults(&openScreen, &openFull, &openPalette, &drawQuality); StartSpinning(); theErr = DoOpenDocument(&theSpec, true, openScreen, kAEOFAlways, gThePrefs.expandSmall, true, openPalette, drawQuality, (*gSlideOptions)->offscreen, (*gSlideOptions)->autoComments, gThePrefs.autoFix, gThePrefs.changeCreator); StopSpinning(&qd.arrow); if (theErr == noErr) { for (theImage = gImageRoot, gSlideNextImage = nil; theImage; theImage = (*theImage)->next) if (SameFile(&(*theImage)->file, &theSpec)) return theImage; } else theImage = HandleLoadError(theErr, theSpec.name); } while (theImage == (ImageHandle)kReloadSlide); return theImage; } //===================================================================================== // ImageHandle HandleLoadError(OSErr theErr) // // Handles errors that occur during a load; abort errors are assumed to be the result // of the user pressing a control button. // // External calls: GetOpenDefaults, DoOpenDocument, StopSpinning, HandleAEError //===================================================================================== static ImageHandle HandleLoadError(OSErr theErr, StringPtr fileName) { Boolean advance; switch (theErr) { case codecAbortErr: if (gDone) return (ImageHandle)kEndSlideShow; else if (gPendingButton != -1) { short button = gPendingButton; gPendingButton = -1; if (button == kPauseButton || button == kHideButton) { gSlideShow = (button == kPauseButton) ? PauseSlideShow(&advance) : HideSlideShow(&advance); if (!gSlideShow) return (ImageHandle)kEndSlideShow; else return (ImageHandle)kReloadSlide; } else if (button == kForwardButton)// && (*gSlideOptions)->userControl) return (ImageHandle)kAdvanceSlide; else if (button == kStopButton) return (ImageHandle)kEndSlideShow; else if (button == kReverseButton) return (ImageHandle)kReverseSlide; } break; case memFullErr: if (WarnSlideShowMemory()) return (ImageHandle)kEndSlideShow; break; default: if (!(*gSlideOptions)->noErrors) HandleAEError(theErr, errNoLoadMemory, fileName); break; } return nil; } //===================================================================================== // Boolean WarnSlideShowMemory(void) // // Display the warning about not being able to see all slides due to low memory. // // External calls: PushPort, MySetPort, StopSpinning, CenterAlert, PopPort //===================================================================================== static Boolean WarnSlideShowMemory(void) { short choice; ShowCursor(); if (!gSlideWarned && !(*gSlideOptions)->noErrors) { gSlideWarned = true; PushPort(); MySetPort(nil); StopSpinning(&qd.arrow); choice = FWCautionAlert(CenterAlert(rSlideMemAlert), gGenericFilter); PopPort(); if (choice == 3 || choice == kDialogCancel) return true; } return false; } //===================================================================================== // Boolean EndSlideShow(void) // // Display the "Slide show has ended" alert. // // External calls: PushPort, MySetPort, StopSpinning, CenterAlert, PopPort //===================================================================================== extern Boolean EndSlideShow(void) { ShowCursor(); if (!gSlideRoot) { MinorError(errNoImagesFound); MyInvalMenuBar(); } else { PushPort(); MySetPort(nil); StopSpinning(&qd.arrow); FWNoteAlert(CenterAlert(rEndSlidesAlert), gGenericFilter); PopPort(); } return false; } //===================================================================================== // Boolean NextSlide(void) // // Switches to the next slide and forces it to be drawn. // // External calls: ChangeActive, DoCloseWindow, UpdateImage //===================================================================================== extern Boolean NextSlide(Boolean *advance) { ImageHandle loadErrorResult; OSErr theErr; // if no slide is ready tell the caller to advance if (!gSlideNextImage) *advance = true; // otherwise, process & draw the next slide else { // obscure the cursor unless it's under user control if (!(*gSlideOptions)->userControl && !GetSlideControlsWindow()) ObscureCursor(); // bring the next window to the front ChangeActive((*gSlideNextImage)->window); // if we're doing a disk-based slide show, close all other images if (!(*gSlideRoot)->mem) { ImageHandle oldImage, nextImage; for (oldImage = gImageRoot; oldImage; oldImage = nextImage) { nextImage = (*oldImage)->next; if (oldImage != gSlideNextImage) DoCloseWindow((*oldImage)->window, gThePrefs.restoreColors); } } // handle the update immediately, so we can begin loading the next guy; we // do this in a loop so that if we get a pause/resume sequence, we can redraw // the image do { SetSlideControlsText(gString[strSlideDrawing], (*gSlideNextImage)->file.name, gNullString, gNullString); theErr = UpdateImage(gSlideNextImage); ResetSlideTimer(); // clear out the next slide pointer and handle any error conditions if (theErr != noErr) { loadErrorResult = HandleLoadError(theErr, nil); if (loadErrorResult == (ImageHandle)kAdvanceSlide) *advance = true; else if (loadErrorResult == (ImageHandle)kEndSlideShow) { CleanUpSlideShow(); return false; } else if (loadErrorResult == (ImageHandle)kReverseSlide) { PointToPreviousSlide(); *advance = true; } } else loadErrorResult = nil; if (loadErrorResult != (ImageHandle)kReloadSlide) gSlideNextImage = nil; } while (loadErrorResult == (ImageHandle)kReloadSlide); } // if we hit the end of the slide show, end it now if (!(*gSlideOptions)->repeat && DisplayedSlide() == LastSlide()) { SetSlideControlButton(kForwardButton, disabled); DrawSlideControlsWindow(); EndSlideShow(); CleanUpSlideShow(); return false; } return true; } \ No newline at end of file diff --git a/Source/C/SlideShowOptions.c b/Source/C/SlideShowOptions.c new file mode 100644 index 0000000..d6e3da8 --- /dev/null +++ b/Source/C/SlideShowOptions.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "SlideShowOptions.h" static Boolean IsValidSlideOptionsDrag(DragReference theDragRef, HFSFlavor *theFile); static pascal OSErr SlideOptionsDragTracker(DragTrackingMessage message, WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef); static pascal OSErr SlideOptionsDragReceiver(WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef); //===================================================================================== // Global variables local to this module //===================================================================================== static DialogPtr gSlideOptionsDialog = nil; static UserItemUPP gSlideOptionsUser = nil; static DragTrackingHandlerUPP gSlideOptionsDragTracker = nil; static DragReceiveHandlerUPP gSlideOptionsDragReceiver = nil; static SlideOptions gOldOptions; static FSSpec gSlideSpec; /* * OpenSlideOptions() * * Purpose: Opens the slide show dialog window * Inputs: none * Returns: nothing * */ OSErr OpenSlideOptions(void) { OSErr theErr = noErr; Str255 theTime; short i; if (gSlideOptionsDialog) { if (!WindowVisible(gSlideOptionsDialog)) FWShowWindow(gSlideOptionsDialog); return noErr; } gOldOptions = **gSlideOptions; gSlideSpec.vRefNum = gSlideSpec.parID = *gSlideSpec.name = 0; GetSlideSpec(&gSlideSpec); if (!(gSlideOptionsDialog = AllocateDialog())) return gIntError = errNoMemory, memFullErr; StartSpinning(); PushPort(); MySetPort(nil); if (gSlideOptionsDialog = FWGetNewDialog(rSlideShowDialog, (Ptr)gSlideOptionsDialog, (WindowPtr)-1)) { if (gDragMgrPresent) { if (!gSlideOptionsDragTracker) { gSlideOptionsDragTracker = NewDragTrackingHandlerProc((ProcPtr)SlideOptionsDragTracker); gSlideOptionsDragReceiver = NewDragReceiveHandlerProc((ProcPtr)SlideOptionsDragReceiver); } InstallTrackingHandler(gSlideOptionsDragTracker, gSlideOptionsDialog, 0); InstallReceiveHandler(gSlideOptionsDragReceiver, gSlideOptionsDialog, 0); } SetItemHandle(gSlideOptionsDialog, slideOutlineUser, (Handle)gOutlineOK); SetItemHandle(gSlideOptionsDialog, slideLeftBoxUser, (Handle)gPopUpMenuBox); SetItemHandle(gSlideOptionsDialog, slideRightBoxUser, (Handle)gPopUpMenuBox); if (!gSlideOptionsUser) gSlideOptionsUser = NewUserItemProc((ProcPtr)SlideOptionsUser); SetItemHandle(gSlideOptionsDialog, slideFolderUser, (Handle)gSlideOptionsUser); i = (*gSlideOptions)->delay; if (i && !(i % 3600)) { SetDCtlValue(gSlideOptionsDialog, slideTimePopUpMenu, timeHours); i /= 3600; } else if (i && !(i % 60)) { SetDCtlValue(gSlideOptionsDialog, slideTimePopUpMenu, timeMinutes); i /= 60; } else SetDCtlValue(gSlideOptionsDialog, slideTimePopUpMenu, timeSeconds); NumToString(i, theTime); SetDIText(gSlideOptionsDialog, slideDelayEdit, theTime); SelIText(gSlideOptionsDialog, slideDelayEdit, 0, 255); UpdateSlideOptionsButtons(); PlaceWindow(gSlideOptionsDialog, &gThePrefs.slideBounds, CenterWindow(gSlideOptionsDialog)); } else gIntError = errNoMemory, theErr = memFullErr, DeallocateDialog(gSlideOptionsDialog); PopPort(); StopSpinning(&qd.arrow); return theErr; } /* * CloseSlideOptions() * * Purpose: Closes the slide show dialog window * Inputs: none * Returns: nothing * */ void CloseSlideOptions(void) { PushPort(); MySetPort(nil); if (gSlideOptionsDialog) { SaveWindowPosition(gSlideOptionsDialog, &gThePrefs.slideBounds); if (gDragMgrPresent) { RemoveTrackingHandler(gSlideOptionsDragTracker, gSlideOptionsDialog); RemoveReceiveHandler(gSlideOptionsDragReceiver, gSlideOptionsDialog); } FWCloseDialog(gSlideOptionsDialog); DisposeHandle(((DialogPeek)gSlideOptionsDialog)->items); DeallocateDialog(gSlideOptionsDialog); } gSlideOptionsDialog = nil; PopPort(); ChangeActive(FWFrontWindow()); } /* * GetSlideOptionsWindow() * * Purpose: Returns a pointer to the slide show dialog * Inputs: none * Returns: nothing * */ WindowPtr GetSlideOptionsWindow(void) { return (WindowPtr)gSlideOptionsDialog; } extern OSErr GetSlideSpec(FSSpec *theSpec) { AliasHandle theAlias; OSErr theErr = noErr; Boolean needsUpdate; short count = 1; theErr = LoadPrefsHandle(kPrefsAliasType, 0, (Handle *)&theAlias); if (theErr == noErr) { theErr = MatchAlias(nil, kARMSearch + kARMSearchMore + kARMNoUI, theAlias, &count, (FSSpecArrayPtr)theSpec, &needsUpdate, nil, 0); if (!count) theErr = fnfErr; DisposeHandle((Handle)theAlias); } if (theErr != noErr) theErr = GetDeskFolderSpec(theSpec, kOnSystemDisk); return theErr; } /* * HandleSlideOptionsEvent(theItem) * * Purpose: Handles events coming in for the slide dialog * Inputs: none * Returns: nothing * */ void HandleSlideOptionsEvent(short theItem) { AliasHandle theAlias; Str255 theTime; FSSpec theSpec; OSErr theErr; short val; switch (theItem) { case kDialogClose: GetDIText(gSlideOptionsDialog, slideDelayEdit, theTime); StringToNum(theTime, &(*gSlideOptions)->delay); val = GetDCtlValue(gSlideOptionsDialog, slideTimePopUpMenu); if (val == timeHours) (*gSlideOptions)->delay *= 3600; else if (val == timeMinutes) (*gSlideOptions)->delay *= 60; SavePrefsHandle(kPrefsSlideType, 0, (Handle)gSlideOptions); theErr = NewAlias(nil, &gSlideSpec, &theAlias); if (theErr == noErr) { SavePrefsHandle(kPrefsAliasType, 0, (Handle)theAlias); DisposeHandle((Handle)theAlias); } gSlideFolderValid = (GetSlideSpec(&theSpec) == noErr); CloseSlideOptions(); return; case kDialogOK: case slideBeginButton: SendCloseWindow(gSlideOptionsDialog); if (gSlideShow) ReinitSlideShow(&gOldOptions); else SendSlideShow(); return; case kDialogCancel: case slideRevertButton: **gSlideOptions = gOldOptions; break; case slideControlMenu: if (GetDCtlValue(gSlideOptionsDialog, slideControlMenu) == slideControlUserItem) (*gSlideOptions)->userControl = true; else (*gSlideOptions)->userControl = false; AdjustMenus(); break; case slideRandomBox: (*gSlideOptions)->random = !(*gSlideOptions)->random; break; case slideRepeatBox: (*gSlideOptions)->repeat = !(*gSlideOptions)->repeat; break; case slideIgnoreErrBox: (*gSlideOptions)->noErrors = !(*gSlideOptions)->noErrors; break; case slideHideWindoidsBox: (*gSlideOptions)->hideWindoids = !(*gSlideOptions)->hideWindoids; break; case slideHideControlsBox: (*gSlideOptions)->hideControls = !(*gSlideOptions)->hideControls; break; case slideAutoCommentsBox: (*gSlideOptions)->autoComments = !(*gSlideOptions)->autoComments; break; case slideSourceMenu: if (GetDCtlValue(gSlideOptionsDialog, slideSourceMenu) == slideSourceMemoryItem) (*gSlideOptions)->fromMemory = true; else (*gSlideOptions)->fromMemory = false; break; case slideSelectButton: theSpec = gSlideSpec; EnableItem(GetMHandle(rAppleMenu), 1); if (StandardGetFolder(&theSpec)) gSlideSpec = theSpec; DisableItem(GetMHandle(rAppleMenu), 1); UpdateDialogItem(gSlideOptionsDialog, slideFolderUser); break; case slideRecursiveBox: (*gSlideOptions)->recursive = !(*gSlideOptions)->recursive; break; case slideImportBox: (*gSlideOptions)->allFiles = !(*gSlideOptions)->allFiles; break; case slideFilenamesBox: (*gSlideOptions)->fileNames = !(*gSlideOptions)->fileNames; break; case slideOffscreenBox: (*gSlideOptions)->offscreen = !(*gSlideOptions)->offscreen; break; } UpdateSlideOptionsButtons(); return; } /* * HandleSlideOptionsKey(theChar, theKey) * * Purpose: Handles key down events in the slide show dialog * Inputs: theChar = the ASCII representation of the character * theKey = the key code of the key pressed * Returns: nothing * */ Boolean HandleSlideOptionsKey(char theChar) { if (theChar == kTabChar) SelIText(gSlideOptionsDialog, slideDelayEdit, 0, 255); else if (((theChar >= '0') && (theChar <= '9')) || (theChar < ' ') || (theChar > '~')) return false; else SysBeep(6); return true; } /* * UpdateSlideOptionsButtons() * * Purpose: Updates the status of the various buttons on the slide show dialog * Inputs: none * Returns: nothing * */ void UpdateSlideOptionsButtons(void) { ControlHandle theControl; FSSpec theSpec; Str31 oldTitle; short itemType; Rect itemRect; OSErr theErr; if (gSlideShow) { GetDItem(gSlideOptionsDialog, slideBeginButton, &itemType, (Handle *)&theControl, &itemRect); GetCTitle(theControl, oldTitle); if (!EqualString(oldTitle, gString[strResume], true, true)) SetCTitle(theControl, gString[strResume]); } else { if (!(*gSlideOptions)->fromMemory) theErr = FSMakeFSSpec(gSlideSpec.vRefNum, gSlideSpec.parID, gSlideSpec.name, &theSpec); if (((*gSlideOptions)->fromMemory && !gImageRoot) || (!(*gSlideOptions)->fromMemory && ((theErr != noErr) || !gSlideSpec.name[0]))) DisableDControl(gSlideOptionsDialog, slideBeginButton); else EnableDControl(gSlideOptionsDialog, slideBeginButton); OutlineOK(gSlideOptionsDialog, slideOutlineUser); } if (!(*gSlideOptions)->userControl) { SetDCtlValue(gSlideOptionsDialog, slideControlMenu, slideControlAutoItem); EnableDControl(gSlideOptionsDialog, slideDelayText); EnableDControl(gSlideOptionsDialog, slideDelayEdit); EnableDControl(gSlideOptionsDialog, slideTimePopUpMenu); } else { SetDCtlValue(gSlideOptionsDialog, slideControlMenu, slideControlUserItem); DisableDControl(gSlideOptionsDialog, slideDelayText); DisableDControl(gSlideOptionsDialog, slideDelayEdit); DisableDControl(gSlideOptionsDialog, slideTimePopUpMenu); } if (gSlideShow) DisableDControl(gSlideOptionsDialog, slideRandomBox); else EnableDControl(gSlideOptionsDialog, slideRandomBox); SetDCtlValue(gSlideOptionsDialog, slideRandomBox, (*gSlideOptions)->random); SetDCtlValue(gSlideOptionsDialog, slideRepeatBox, (*gSlideOptions)->repeat); SetDCtlValue(gSlideOptionsDialog, slideIgnoreErrBox, (*gSlideOptions)->noErrors); SetDCtlValue(gSlideOptionsDialog, slideHideControlsBox, (*gSlideOptions)->hideControls); SetDCtlValue(gSlideOptionsDialog, slideHideWindoidsBox, (*gSlideOptions)->hideWindoids); SetDCtlValue(gSlideOptionsDialog, slideFilenamesBox, (*gSlideOptions)->fileNames); SetDCtlValue(gSlideOptionsDialog, slideAutoCommentsBox, (*gSlideOptions)->autoComments); if (gSlideShow) DisableDControl(gSlideOptionsDialog, slideSourceMenu); if ((*gSlideOptions)->fromMemory) { SetDCtlValue(gSlideOptionsDialog, slideSourceMenu, slideSourceMemoryItem); DisableDControl(gSlideOptionsDialog, slideSelectButton); DisableDControl(gSlideOptionsDialog, slideRecursiveBox); DisableDControl(gSlideOptionsDialog, slideImportBox); DisableDControl(gSlideOptionsDialog, slideOffscreenBox); SetDCtlValue(gSlideOptionsDialog, slideRecursiveBox, false); SetDCtlValue(gSlideOptionsDialog, slideImportBox, false); SetDCtlValue(gSlideOptionsDialog, slideOffscreenBox, false); } else { SetDCtlValue(gSlideOptionsDialog, slideSourceMenu, slideSourceDiskItem); if (gSlideShow) { DisableDControl(gSlideOptionsDialog, slideSelectButton); DisableDControl(gSlideOptionsDialog, slideRecursiveBox); DisableDControl(gSlideOptionsDialog, slideImportBox); } else { EnableDControl(gSlideOptionsDialog, slideSelectButton); EnableDControl(gSlideOptionsDialog, slideRecursiveBox); EnableDControl(gSlideOptionsDialog, slideImportBox); } SetDCtlValue(gSlideOptionsDialog, slideRecursiveBox, (*gSlideOptions)->recursive); SetDCtlValue(gSlideOptionsDialog, slideImportBox, (*gSlideOptions)->allFiles); EnableDControl(gSlideOptionsDialog, slideOffscreenBox); SetDCtlValue(gSlideOptionsDialog, slideOffscreenBox, (*gSlideOptions)->offscreen); } SlideOptionsUser(gSlideOptionsDialog, slideFolderUser); } /* * SlideUser(theDialog, theItem) * * Purpose: Draws the name of the currently selected directory * Inputs: theDialog = dialog pointer to the slide show dialog * theItem = the item number of interest * Returns: nothing * */ pascal void SlideOptionsUser(DialogPtr theDialog, short theItem) { Handle itemHandle, thePath; short itemType, length; Str255 theString; FSSpec theSpec; Rect itemRect; PushPort(); MySetPort((CGrafPtr)theDialog); TextFont(systemFont); TextSize(12); TextMode((*gSlideOptions)->fromMemory ? grayishTextOr : srcCopy); GetDItem(theDialog, theItem, &itemType, &itemHandle, &itemRect); if (GetDeskFolderSpec(&theSpec, gSlideSpec.vRefNum) == noErr && SameFile(&gSlideSpec, &theSpec)) { theString[0] = 0; AddString(theString, gString[strDesktop]); } else if (GetFullPath(&gSlideSpec, &thePath) == noErr && gSlideSpec.name[0]) { HLock(thePath); length = GetHandleSize(thePath); TruncText(Width(&itemRect), *thePath, &length, smTruncMiddle); BlockMove(*thePath, &theString[1], length); theString[0] = length; DisposeHandle(thePath); } else { theString[0] = 0; AddString(theString, gString[strSSNone]); } EraseRect(&itemRect); MoveTo(itemRect.left + ((Width(&itemRect) - StringWidth(theString)) >> 1), itemRect.bottom - 5); DrawString(theString); TextMode(srcCopy); PopPort(); } static Boolean IsValidSlideOptionsDrag(DragReference theDragRef, HFSFlavor *theFile) { Size theSize = sizeof(HFSFlavor); ItemReference theItem; ushort count; OSErr theErr; theErr = CountDragItems(theDragRef, &count); if (theErr == noErr && count == 1) { theErr = GetDragItemReferenceNumber(theDragRef, 1, &theItem); if (theErr == noErr) { theErr = GetFlavorData(theDragRef, theItem, flavorTypeHFS, theFile, &theSize, 0); if (theErr == noErr && ( theFile->fileType == 'fold' || theFile->fileType == 'disk' || theFile->fileType == 'fdrp' || theFile->fileType == 'trsh' || theFile->fileType == 'hdsk' || theFile->fileType == 'flpy' || theFile->fileType == 'srvr' || theFile->fileType == 'drop' || theFile->fileType == 'fasy' || theFile->fileType == 'faam' || theFile->fileType == 'fast' || theFile->fileType == 'fapn' || theFile->fileType == 'fapf' || theFile->fileType == 'fact' || theFile->fileType == 'faex' || theFile->fileType == 'faet' || theFile->fileType == 'fash' || theFile->fileType == 'famn')) return true; } } return false; } static pascal OSErr SlideOptionsDragTracker(DragTrackingMessage message, WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef) { #if applec #pragma unused(handlerRefCon) #endif HFSFlavor theFile; if (message == dragTrackingEnterWindow || message == dragTrackingLeaveWindow) if (IsValidSlideOptionsDrag(theDragRef, &theFile)) { RgnHandle theRgn = NewRgn(); if (theRgn) { RectRgn(theRgn, &theWindow->portRect); if (message == dragTrackingEnterWindow) ShowDragHilite(theDragRef, theRgn, true); else if (message == dragTrackingLeaveWindow) HideDragHilite(theDragRef); DisposeRgn(theRgn); } } return noErr; } static pascal OSErr SlideOptionsDragReceiver(WindowPtr theWindow, void *handlerRefCon, DragReference theDragRef) { #if applec #pragma unused(theWindow, handlerRefCon) #endif Boolean wasAliased, isFolder; HFSFlavor theFile; OSErr theErr; if (IsValidSlideOptionsDrag(theDragRef, &theFile)) { theErr = ResolveAliasFile(&theFile.fileSpec, true, &isFolder, &wasAliased); if (theErr == noErr && isFolder) { gSlideSpec = theFile.fileSpec; UpdateDialogItem(gSlideOptionsDialog, slideFolderUser); return noErr; } } return dragNotAcceptedErr; } \ No newline at end of file diff --git a/Source/C/StandardFolder.c b/Source/C/StandardFolder.c new file mode 100644 index 0000000..4cf86d2 --- /dev/null +++ b/Source/C/StandardFolder.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Global variables: * * lDeskFolderSpec = FSSpec record for the current desktop folder * */ static FSSpec gDeskFolderSpec; static Boolean gReallyCancelled = true; static DlgHookYDUPP gStdFolderHook = nil; /* * StandardGetFolder(theSpec) * * Purpose: Uses the DTS code to allow the user to select a folder * Inputs: theSpec = the destination FSSpec to stuff the dirID and vRefNum * Returns: true if it wasn't cancelled * */ Boolean StandardGetFolder(FSSpec *theSpec) { short activeList[2] = { 1, sfItemFileListUser }; Point where = CenterDialogWhere(rFolderDialog); Boolean isFolder, wasAliased; StandardFileReply sfReply; Str255 dummyString = "\p"; SFData sfUserData; OSErr theErr; sfUserData.replyPtr = &sfReply; sfUserData.origSelection = *theSpec; sfUserData.oldSelection.vRefNum = -9999; gReallyCancelled = true; MySetPort(nil); StopSpinning(&qd.arrow); GetDeskFolderSpec(&gDeskFolderSpec, sfUserData.origSelection.vRefNum); if (!gStdFolderHook) gStdFolderHook = NewDlgHookYDProc((ProcPtr)StdFolderHook); CustomPutFile(gNullString, dummyString, &sfReply, rFolderDialog, where, gStdFolderHook, gOpenSaveModalFilter, activeList, nil, &sfUserData); sfReply.sfGood = !gReallyCancelled; if (sfReply.sfGood) { if (MakeCanonFSSpec(&sfReply.sfFile) != noErr) return false; if (ResolveAliasFile(&sfReply.sfFile, true, &isFolder, &wasAliased) != noErr) return false; } theErr = FSMakeFSSpec(sfReply.sfFile.vRefNum, sfReply.sfFile.parID, sfReply.sfFile.name, theSpec); if (theErr != noErr) return false; return sfReply.sfGood; } /* * StdFolderHook(item, theDialog, userData) * * Purpose: Called by CustomGetFile to handle our special button * Inputs: item = the item number hit * theDialog = pointer to the dialog record * userData = pointer to our data * Returns: the item number hit * */ pascal short StdFolderHook(short item, DialogPtr theDialog, Ptr userData) { static short gLastItem = 0, gLastVRefNum = 555; SFDataPtr sfUserData = (SFDataPtr)userData; SysEnvRec theEnvirons; FSSpec curSpec; long theID; if (gLastItem == sfItemEjectButton) { SysEnvirons(1, &theEnvirons); if (theEnvirons.sysVRefNum != gLastVRefNum) UnmountVol(0, gLastVRefNum); } if (GetWRefCon(theDialog) != sfMainDialogRefCon) return item; if (item == sfHookFirstCall) { curSpec = sfUserData->origSelection; GetDirectoryID(&curSpec, &theID); curSpec.parID = theID; curSpec.name[0] = 0; sfUserData->replyPtr->sfFile = curSpec; FWDeactivate(); StopSpinning(&qd.arrow); return sfHookChangeSelection; } else if (item == sfHookLastCall) { FWActivate(); return item; } curSpec = sfUserData->replyPtr->sfFile; if (!SameFile(&curSpec, &sfUserData->oldSelection)) { MakeCanonFSSpec(&curSpec); if (curSpec.vRefNum != sfUserData->oldSelection.vRefNum) GetDeskFolderSpec(&gDeskFolderSpec, curSpec.vRefNum); SetSelectButtonName(curSpec.name, ShouldHiliteSelect(&curSpec), theDialog); sfUserData->oldSelection = sfUserData->replyPtr->sfFile; } if (item == folderSelectButton) { item = sfItemCancelButton; gReallyCancelled = false; } gLastVRefNum = sfUserData->replyPtr->sfFile.vRefNum; return gLastItem = item; } /* * SetSelectButtonName(selName, hilited, theDialog) * * Purpose: Set the name of the Select button in our folder dialog * Inputs: selName = the new name * hilited = whether we should enable the button or not * theDialog = pointer to our dialog * Returns: nothing * */ void SetSelectButtonName(StringPtr selName, Boolean hilited, DialogPtr theDialog) { Str255 storeName, tempLenStr, tempSelName; short itemType, width; Handle itemHandle; Rect itemRect; BlockMove(selName, tempSelName, selName[0] + 1); GetDItem(theDialog, folderSelectButton, &itemType, &itemHandle, &itemRect); width = itemRect.right - itemRect.left; BlockMove(gString[strSelect], tempLenStr, *gString[strSelect] + 1); AddCString(tempLenStr, " ÒÓ ", 5); width -= StringWidth(tempLenStr); TruncString(width, tempSelName, smTruncMiddle); BlockMove(gString[strSelect], storeName, *gString[strSelect] + 1); AddCString(storeName, " Ò", 2); AddString(storeName, tempSelName); AddChar(storeName, 'Ó'); SetCTitle((ControlHandle)itemHandle, storeName); SetDItem(theDialog, folderSelectButton, itemType, itemHandle, &itemRect); HiliteControl((ControlHandle)itemHandle, hilited ? 0 : 255); } /* * MakeCanonFSSpec(theSpec) * * Purpose: Checks and creates a FSSpec record for the given directory * Inputs: theSpec = the spec to check * Returns: OSErr if there's a problem * */ OSErr MakeCanonFSSpec(FSSpec *theSpec) { DirInfo infoPB; OSErr err; if (theSpec->name[0] != '\0') return fnfErr; infoPB.ioNamePtr = theSpec->name; infoPB.ioVRefNum = theSpec->vRefNum; infoPB.ioDrDirID = theSpec->parID; infoPB.ioFDirIndex = -1; err = PBGetCatInfo((CInfoPBPtr)&infoPB, false); theSpec->parID = infoPB.ioDrParID; return err; } /* * GetDeskFolderSpec(theSpec, vRefNum) * * Purpose: Get the desktop folder's FSSpec for the given vRefNum * Inputs: theSpec = the spec we want * vRefNum = the volume reference number for the folder we desire * Returns: OSErr if there's a problem * */ extern OSErr GetDeskFolderSpec(FSSpec *theSpec, short vRefNum) { OSErr err; theSpec->name[0] = '\0'; if ((err = FindFolder(vRefNum, kDesktopFolderType, kDontCreateFolder, &theSpec->vRefNum, &theSpec->parID)) != noErr) return err; return MakeCanonFSSpec(theSpec); } /* * ShouldHiliteSelect(theSpec) * * Purpose: Checks the validity of the given folder and says if we should enable it * Inputs: theSpec = the spec we want * Returns: true to enable, false to disable * */ Boolean ShouldHiliteSelect(FSSpec *theSpec) { if (SameFile(theSpec, &gDeskFolderSpec)) BlockMove(gString[strDesktop], theSpec->name, *gString[strDesktop] + 1); return true; } extern Boolean SameFile(FSSpec *file1, FSSpec *file2) { return (file1->vRefNum == file2->vRefNum && file1->parID == file2->parID && EqualString(file1->name, file2->name, false, true)); } \ No newline at end of file diff --git a/Source/C/StatisticsWindow.c b/Source/C/StatisticsWindow.c new file mode 100644 index 0000000..dacdaae --- /dev/null +++ b/Source/C/StatisticsWindow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * Local variables: * lStatFontInfo = the font information for the statistics window font (Geneva 9pt) * lStatWindow = pointer to the statistics window * */ static RgnHandle gStatRegion = nil; static Ptr gStatRecord = nil; static long gStatLength = 0; static Rect gStatRect[strFreeMemory - strFileName + 2]; static ImageHandle gLastImage = (ImageHandle)-1; static WindowPtr gStatWindow = nil; static TEHandle gCreditsTE = nil; static FontInfo gStatFontInfo; static long gCreditsHeight; /* * OpenStats() * * Purpose: Creates and initializes the statistics window * Inputs: none * Returns: nothing * */ OSErr OpenStats(void) { Handle textHandle, stylHandle; Rect theRect, mainRect; OSErr theErr = noErr; LHHandle theLines; Point where; short i; if (gStatWindow) { if (!WindowVisible(gStatWindow)) FWShowWindow(gStatWindow); return noErr; } if (!(gStatWindow = AllocateWindow())) return gIntError = errNoMemory, memFullErr; PushPort(); MySetPort(nil); if (gStatWindow = FWGetNewFloatingWindow(rStatWindow, (Ptr)gStatWindow, (WindowPtr)-1)) { MySetPort((CGrafPtr)gStatWindow); TextFont(geneva); TextSize(9); TextMode(srcCopy); TextFace(bold); GetFontInfo(&gStatFontInfo); gStatFontInfo.widMax = StringWidth(gString[strDisplayedColors]) + 8; SizeStats(true); theRect = gStatWindow->portRect; InsetRect(&theRect, 2, 2); if (gCreditsTE = TEStylNew(&theRect, &gStatWindow->portRect)) { if (textHandle = GetResource('TEXT', rCreditsText)) { if (stylHandle = GetResource('styl', rCreditsText)) { HLock(textHandle); HLock(stylHandle); TEStylInsert(*textHandle, GetHandleSize(textHandle), (StScrpHandle)stylHandle, gCreditsTE); ReleaseResource(stylHandle); } else TEDispose(gCreditsTE), gCreditsTE = nil; ReleaseResource(textHandle); } else TEDispose(gCreditsTE), gCreditsTE = nil; if (gCreditsTE) { TESetJust(teCenter, gCreditsTE); if ((*gCreditsTE)->lineHeight == -1 || (*gCreditsTE)->fontAscent == -1) { theLines = (*GetStylHandle(gCreditsTE))->lhTab; for (i = gCreditsHeight = 0; i < (*gCreditsTE)->nLines; i++) gCreditsHeight += (*theLines)[i].lhHeight; } else gCreditsHeight = (*gCreditsTE)->nLines * (*gCreditsTE)->lineHeight; } } SizeStats(gThePrefs.statsZoomed); theRect = gStatWindow->portRect; OffsetRect(&theRect, -theRect.left, -theRect.top); if (gThePrefs.statsBounds.top != gThePrefs.statsBounds.bottom) { gThePrefs.statsBounds.right = gThePrefs.statsBounds.left + Width(&theRect); gThePrefs.statsBounds.bottom = gThePrefs.statsBounds.top + Height(&theRect); } GetActiveRect(gMainMonitor, &mainRect); where.h = mainRect.left + kWindowBorderWidth; where.v = mainRect.bottom - kWindowBorderHeight - theRect.bottom; PlaceWindow(gStatWindow, &gThePrefs.statsBounds, where); gLastImage = (ImageHandle)-1; gThePrefs.statsOpen = true; } else gIntError = errNoMemory, theErr = memFullErr, DeallocateWindow(gStatWindow); PopPort(); return theErr; } /* * CloseStats() * * Purpose: Closes the statistics window * Inputs: none * Returns: nothing * */ void CloseStats(void) { PushPort(); MySetPort(nil); if (gCreditsTE) TEDispose(gCreditsTE), gCreditsTE = nil; if (gStatWindow) { gThePrefs.statsOpen = false; SaveWindowPosition(gStatWindow, &gThePrefs.statsBounds); FWCloseWindow(gStatWindow); DeallocateWindow(gStatWindow); } gStatWindow = nil; PopPort(); } /* * SizeStats(zoomed) * * Purpose: Sets the size of the statistics window appropriately * Inputs: zoomed = true if the window is zoomed to its large size * Returns: nothing * */ void SizeStats(Boolean zoomed) { short line = gStatFontInfo.leading + gStatFontInfo.ascent + gStatFontInfo.descent; short width, height; width = 5 * gStatFontInfo.widMax / 2 + 20; height = gStatFontInfo.leading + gStatFontInfo.descent; if (zoomed) height += 15 * line; else height += line; SizeWindow(gStatWindow, width, height, false); PushPort(); MySetPort((CGrafPtr)gStatWindow); EraseRect(&gStatWindow->portRect); DrawStatWindow(); PopPort(); } /* * ZoomStats(zoomed) * * Purpose: Toggles the zoomed state of the stats window * Inputs: none * Returns: nothing * */ void ZoomStats(void) { gThePrefs.statsZoomed = !gThePrefs.statsZoomed; SizeStats(gThePrefs.statsZoomed); } /* * GetStatWindow() * * Purpose: Returns a pointer to the statistics window * Inputs: none * Returns: nothing * */ WindowPtr GetStatWindow(void) { return gStatWindow; } /* * SetStatistics() * * Purpose: Updates the statistics window * Inputs: none * Returns: nothing * */ void SetStatistics(void) { if (gStatWindow) { PushPort(); MySetPort((CGrafPtr)gStatWindow); InvalRect(&gStatWindow->portRect); PopPort(); } if (GetCommentsWindow()) DrawCommentsWindow(); } /* * DrawStatWindow() * * Purpose: Draws the statistics window * Inputs: none * Returns: nothing * */ void DrawStatWindow(void) { static Boolean gCreditsLast = false; short vPos = gStatFontInfo.ascent + gStatFontInfo.leading; ImageHandle theImage = nil; WindowPtr theWindow; if (!gStatRegion) gStatRegion = NewRgn(); else SetEmptyRgn(gStatRegion); CalcVis((WindowPeek)gStatWindow); for (theWindow = GetFirstWindow(); theWindow && !(theImage = FindImage(theWindow)); theWindow = NextWindow(theWindow)); if (theImage != gLastImage) gLastImage = theImage; if (theImage && IsAboutBox(theImage)) { if (gCreditsTE) { TEUpdate(&gStatWindow->portRect, gCreditsTE); gCreditsLast = true; } } else { if (gCreditsLast) { EraseRect(&gStatWindow->portRect); gCreditsLast = false; } if (gThePrefs.statsZoomed) { DrawStatFileName(theImage, &vPos); DrawStatImageSize(theImage, &vPos); DrawStatImageColors(theImage, &vPos); DrawStatImageStatus(theImage, &vPos); DrawStatCompression(theImage, &vPos); DrawStatFileFormat(theImage, &vPos); DrawStatImageLength(theImage, &vPos); DrawStatDisplayedSize(theImage, &vPos); DrawStatDisplayedColors(theImage, &vPos); DrawStatDisplayQuality(theImage, &vPos); DrawStatDisplayTime(theImage, &vPos); DrawStatOffscreen(theImage, &vPos); DrawStatFree(theImage, &vPos); if (theImage && (gThePrefs.reminderCount == 10000)) gThePrefs.reminderCount = 0; } else DrawStatSummary(theImage, &vPos); } if (GetCommentsWindow() && !gStatRecord) DrawCommentsWindow(); } /* * DrawStatSummary(theImage, vPos) * * Purpose: Draws a single-line summary for given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatSummary(ImageHandle theImage, short *vPos) { Str255 theVal; theVal[0] = 0; if (theImage) { AddString(theVal, gString[strSummary1]); StuffString(theVal, 1, (*theImage)->file.name); StuffNumber(theVal, 2, (GetHandleSize((*theImage)->data) + 1023L) >> 10); StuffString(theVal, 3, (*theImage)->format->formatName); StuffNumber(theVal, 4, Width(&(*theImage)->crect)); StuffNumber(theVal, 5, Height(&(*theImage)->crect)); StuffDepth(theVal, 6, (*theImage)->depth); DrawStatItem(*vPos, -1, theVal); } else { long temp; AddString(theVal, gString[strFreeMemory1]); temp = (FreeMem() + 1023 - gMemSlop) >> 10; if (temp < 0) temp = 0; StuffNumber(theVal, 1, temp); DrawStatItem(*vPos, strFreeMemory, theVal); } *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatFileName(theImage, vPos) * * Purpose: Draws the file name of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatFileName(ImageHandle theImage, short *vPos) { Str255 theVal; theVal[0] = 0; if (theImage) AddString(theVal, (*theImage)->file.name); else if (gThePrefs.reminderCount > 20) gThePrefs.reminderCount = 10000; DrawStatItem(*vPos, strFileName, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatImageSize(theImage, vPos) * * Purpose: Draws the size of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatImageSize(ImageHandle theImage, short *vPos) { Str255 theVal; theVal[0] = 0; if (theImage) { Rect theRect = (*theImage)->grect; if (Cropped(theImage)) AddString(theVal, gString[strImageSize2]); else AddString(theVal, gString[strImageSize1]); StuffNumber(theVal, 1, Width(&(*theImage)->crect)); StuffNumber(theVal, 2, Height(&(*theImage)->crect)); StuffNumber(theVal, 3, Width(&theRect)); StuffNumber(theVal, 4, Height(&theRect)); } DrawStatItem(*vPos, strImageSize, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatImageStatus(theImage, vPos) * * Purpose: Draws the status of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatImageStatus(ImageHandle theImage, short *vPos) { Str255 theVal; Boolean comma; theVal[0] = 0; if (theImage) { comma = false; if (Banded(theImage)) { AddString(theVal, gString[strBanded]); comma = true; } if (Cropped(theImage)) { if (comma) { AddChar(theVal, gListSep); AddChar(theVal, ' '); } AddString(theVal, gString[strCropped]); comma = true; } if (Corrupt(theImage)) { if (comma) { AddChar(theVal, gListSep); AddChar(theVal, ' '); } AddString(theVal, gString[strCorrupt]); comma = true; } if (Aborted(theImage)) { if (comma) { AddChar(theVal, gListSep); AddChar(theVal, ' '); } AddString(theVal, gString[strAborted]); comma = true; } if (!comma) AddString(theVal, gString[strNormal]); } DrawStatItem(*vPos, strImageStatus, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatImageColors(theImage, vPos) * * Purpose: Draws the depth of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatImageColors(ImageHandle theImage, short *vPos) { Str255 theVal; short i; theVal[0] = 0; if (theImage) { i = (*theImage)->depth; if ((((*theImage)->depth == 8) && ((*theImage)->compression == kJPEGCompression)) || (i > 32)) AddString(theVal, gString[strImageColors2]); else AddString(theVal, gString[strImageColors1]); StuffDepth(theVal, 1, i); } DrawStatItem(*vPos, strImageColors, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatCompression(theImage, vPos) * * Purpose: Draws the compression type of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatCompression(ImageHandle theImage, short *vPos) { Str255 theVal; theVal[0] = 0; if (theImage) BlockMove((*theImage)->compressionDesc, theVal, *(*theImage)->compressionDesc + 1); DrawStatItem(*vPos, strCompression, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatFileFormat(theImage, vPos) * * Purpose: Draws the file format of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatFileFormat(ImageHandle theImage, short *vPos) { Str255 theVal; theVal[0] = 0; if (theImage) AddString(theVal, (*theImage)->format->formatName); DrawStatItem(*vPos, strFileFormat, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatImageLength(theImage, vPos) * * Purpose: Draws the image size of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatImageLength(ImageHandle theImage, short *vPos) { long csize, psize; Str255 theVal; theVal[0] = 0; if (theImage) { csize = GetHandleSize((*theImage)->data) << 3; if ((*theImage)->compression) { psize = ((*theImage)->depth == 32) ? 24 : (*theImage)->depth; psize *= (long)Height(&(*theImage)->grect) * (long)Width(&(*theImage)->grect); if ((csize * 5L) > psize) { AddString(theVal, gString[strImageLength2]); if (csize > psize) StuffNumber(theVal, 2, 0); else StuffNumber(theVal, 2, 100L * (psize - csize) / psize); } else { AddString(theVal, gString[strImageLength3]); StuffNumber(theVal, 2, psize / csize); } } else AddString(theVal, gString[strImageLength1]); csize = ((csize >> 3) + 1023L) >> 10; StuffNumber(theVal, 1, csize); } DrawStatItem(*vPos, strImageLength, theVal); *vPos += (gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent) << 1; } /* * DrawStatDisplayedSize(theImage, vPos) * * Purpose: Draws the displayed size of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatDisplayedSize(ImageHandle theImage, short *vPos) { long scaleX, scaleY; Str255 theVal; theVal[0] = 0; if (theImage) { if (!EqualSizeRect(&(*theImage)->wrect, &(*theImage)->crect)) { scaleX = 200L * (long)Width(&(*theImage)->wrect) / Width(&(*theImage)->crect); scaleX = (scaleX + 1) >> 1; scaleY = 200L * (long)Height(&(*theImage)->wrect) / Height(&(*theImage)->crect); scaleY = (scaleY + 1) >> 1; if (abs(scaleX - scaleY) <= 1) { AddString(theVal, gString[strDisplayedSize2]); StuffNumber(theVal, 3, (scaleX + scaleY) / 2); } else { AddString(theVal, gString[strDisplayedSize3]); StuffNumber(theVal, 3, scaleX); StuffNumber(theVal, 4, scaleY); } } else AddString(theVal, gString[strDisplayedSize1]); StuffNumber(theVal, 1, Width(&(*theImage)->wrect)); StuffNumber(theVal, 2, Height(&(*theImage)->wrect)); } DrawStatItem(*vPos, strDisplayedSize, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatDisplayedColors(theImage, vPos) * * Purpose: Draws the displayed colors of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatDisplayedColors(ImageHandle theImage, short *vPos) { Str255 theVal; short depth; theVal[0] = 0; if (theImage) { depth = (*(*theImage)->dmon)->depth; if (depth < 4 || depth > 8) { if (Dithered(theImage)) AddString(theVal, gString[strDisplayedColors1]); else AddString(theVal, gString[strDisplayedColors2]); StuffDepth(theVal, 1, depth); } else { switch ((*theImage)->npalette) { case plSys: if (Dithered(theImage)) AddString(theVal, gString[strSystemColors1]); else AddString(theVal, gString[strSystemColors2]); break; case plGrey: if (Dithered(theImage)) AddString(theVal, gString[strGrayscales1]); else AddString(theVal, gString[strGrayscales2]); break; case plImage: if (Dithered(theImage)) AddString(theVal, gString[strImageColorsX1]); else AddString(theVal, gString[strImageColorsX2]); break; case plQuant: if (Dithered(theImage)) AddString(theVal, gString[strReducedColors1]); else AddString(theVal, gString[strReducedColors2]); break; default: if (Dithered(theImage)) AddString(theVal, gString[strDisplayedColors1]); else AddString(theVal, gString[strDisplayedColors2]); break; } StuffDepth(theVal, 1, depth); } } DrawStatItem(*vPos, strDisplayedColors, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatDisplayQuality(theImage, vPos) * * Purpose: Draws the display quality of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatDisplayQuality(ImageHandle theImage, short *vPos) { Str255 theVal; short depth; theVal[0] = 0; if (theImage) { depth = (*(*theImage)->dmon)->depth; if ((depth > 8) || ((depth == 8) && ((*theImage)->npalette != plSys) && ((*theImage)->npalette != plGrey))) { if ((*theImage)->depth >= 24) { switch ((*theImage)->quality) { case iqVHigh: AddString(theVal, gString[strVeryHigh]); break; case iqHigh: if (depth < 24) { AddString(theVal, gString[strHigh]); break; } case iqMedium: AddString(theVal, gString[strNormal]); break; default: AddString(theVal, gString[strNA]); } } else AddString(theVal, gString[strNA]); } else AddString(theVal, gString[strNA]); } DrawStatItem(*vPos, strDisplayQuality, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatDisplayTime(theImage, vPos) * * Purpose: Draws the display time of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatDisplayTime(ImageHandle theImage, short *vPos) { Str255 theVal; theVal[0] = 0; if (theImage) { if ((*theImage)->dtime) { AddString(theVal, gString[strDisplayTime1]); StuffNumber(theVal, 1, ((*theImage)->dtime + 50L) / 1000L); StuffNumber(theVal, 2, (((*theImage)->dtime + 50L) / 100L) % 10L); } else AddString(theVal, gString[strNA]); } DrawStatItem(*vPos, strDisplayTime, theVal); *vPos += gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent; } /* * DrawStatOffscreen(theImage, vPos) * * Purpose: Draws the gworld size of the given image * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatOffscreen(ImageHandle theImage, short *vPos) { Str255 theVal; theVal[0] = 0; if (theImage) { if ((*theImage)->gworld) { if (GWOrigSize(theImage)) AddString(theVal, gString[strOffscreenBitmap2]); else AddString(theVal, gString[strOffscreenBitmap1]); StuffNumber(theVal, 1, (GWorldSize((*theImage)->gworld) + 1023L) >> 10); } else AddString(theVal, gString[strNoBitmap]); } DrawStatItem(*vPos, strOffscreenBitmap, theVal); *vPos += (gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent) << 1; } /* * DrawStatFree(theImage, vPos) * * Purpose: Draws the amount of free memory left * Inputs: theImage = pointer to the image record * vPos = pointer to the vertical position of the item * Returns: nothing * */ void DrawStatFree(ImageHandle theImage, short *vPos) { #if applec #pragma unused(theImage) #endif Str255 theVal; long temp; theVal[0] = 0; temp = (FreeMem() + 1023 - gMemSlop) >> 10; if (temp < 0) temp = 0; AddString(theVal, gString[strFreeMemory1]); StuffNumber(theVal, 1, temp); DrawStatItem(*vPos, strFreeMemory, theVal); *vPos += (gStatFontInfo.ascent + gStatFontInfo.leading + gStatFontInfo.descent) << 1; } /* * DrawStatItem() * * Purpose: Draws a given string in the statistics window, clearing off any old text * Inputs: vPos = the vertical position of the item * item = the item number * theNum = the new value of the item * Returns: nothing * */ void DrawStatItem(short vPos, short item, StringPtr theNum) { short rectItem = gThePrefs.statsZoomed ? item - strFileName : 0; uchar *theName; Rect theRect; gStatRect[rectItem].top = vPos - gStatFontInfo.ascent - gStatFontInfo.leading; gStatRect[rectItem].bottom = vPos + gStatFontInfo.descent; if (gThePrefs.statsZoomed) { TextFace(bold); gStatRect[rectItem].left = gStatFontInfo.widMax - StringWidth(gString[item]); MoveTo(gStatRect[rectItem].left, vPos); if (gStatRecord) BlockMove(&gString[item][1], &gStatRecord[gStatLength], *gString[item]), gStatLength += *gString[item]; else DrawString(gString[item]); } else { gStatRect[rectItem].left = 3; TextFace(bold); MoveTo(gStatRect[rectItem].left, vPos); if (item != -1) { if (gStatRecord) BlockMove(&gString[item][1], &gStatRecord[gStatLength], *gString[item]), gStatLength += *gString[item]; else DrawString(gString[item]); } else { short oldLen = *theNum; theName = theNum++; *theName = 1; while (*theNum++ != ':') (*theName)++; *theNum = oldLen - *theName - 1; if (gStatRecord) BlockMove(&theName[1], &gStatRecord[gStatLength], *theName), gStatLength += *theName; else DrawString(theName); } if (gStatRecord) gStatRecord[gStatLength++] = ' '; else DrawChar(' '); } if (gThePrefs.statsZoomed) theRect.left = gStatFontInfo.widMax + 3; else if (item == -1) theRect.left = 3 + StringWidth(theName) + CharWidth(' '); else theRect.left = 3 + StringWidth(gString[item]) + CharWidth(' '); theRect.right = gStatWindow->portRect.right; theRect.top = vPos - gStatFontInfo.ascent; theRect.bottom = vPos + gStatFontInfo.descent; if (theNum[0]) { TextFace(normal); MoveTo(theRect.left, vPos); if (gStatRecord) BlockMove(&theNum[1], &gStatRecord[gStatLength], *theNum), gStatLength += *theNum; else DrawString(theNum); theRect.left += StringWidth(theNum); } else if (gThePrefs.reminderCount == 10000) { TextFace(normal); if (!gStatRecord) EraseRect(&theRect); theRect.left += (Width(&theRect) - StringWidth(gString[strNagMessages + item])) >> 1; MoveTo(theRect.left, vPos); if (gStatRecord) BlockMove(&gString[strNagMessages + item][1], &gStatRecord[gStatLength], *gString[strNagMessages + item]), gStatLength += *gString[strNagMessages + item]; else DrawString(gString[strNagMessages + item]); theRect.left = theRect.right; } else theRect.left = gStatFontInfo.widMax; gStatRect[rectItem].right = theRect.left; if (!gStatRecord) EraseRect(&theRect); if (gStatRecord) gStatRecord[gStatLength++] = '\r'; if (gStatRegion) { RgnHandle tempRgn = NewRgn(); if (tempRgn) { RectRgn(tempRgn, &gStatRect[rectItem]); UnionRgn(gStatRegion, tempRgn, gStatRegion); DisposeRgn(tempRgn); } } } extern void IdleCredits(void) { ImageHandle theImage = nil; WindowPtr theWindow; if (!gStatWindow) return; for (theWindow = GetFirstWindow(); theWindow && !(theImage = FindImage(theWindow)); theWindow = NextWindow(theWindow)); if (theImage && IsAboutBox(theImage) && gCreditsTE) { PushPort(); MySetPort((CGrafPtr)gStatWindow); CalcVis((WindowPeek)gStatWindow); if (((*gCreditsTE)->viewRect.top - (*gCreditsTE)->destRect.top) >= gCreditsHeight) TEScroll(0, (*gCreditsTE)->viewRect.top - (*gCreditsTE)->destRect.top, gCreditsTE); else TEScroll(0, -1, gCreditsTE); PopPort(); } } extern void HandleStatClick(EventRecord *theEvent) { Point localPt = theEvent->where; PushPort(); MySetPort((CGrafPtr)gStatWindow); GlobalToLocal(&localPt); PopPort(); if (gStatRegion && PtInRgn(localPt, gStatRegion) && gDragMgrPresent && WaitMouseMoved(theEvent->where)) { RgnHandle theRgn = NewRgn(), tempRgn = NewRgn(); DragReference theDrag; char statText[1024]; OSErr theErr; if (theRgn && tempRgn) { theErr = NewDrag(&theDrag); if (theErr == noErr) { gStatRecord = statText; gStatLength = 0; PushPort(); MySetPort((CGrafPtr)gStatWindow); DrawStatWindow(); PopPort(); gStatRecord = nil; AddDragItemFlavor(theDrag, (ItemReference)statText, 'TEXT', statText, gStatLength, 0); CopyRgn(gStatRegion, theRgn); GlobalRgn(theRgn, gStatWindow); CopyRgn(theRgn, tempRgn); InsetRgn(tempRgn, 1, 1); DiffRgn(theRgn, tempRgn, theRgn); SetDragItemBounds(theDrag, (ItemReference)statText, &(*theRgn)->rgnBBox); SetCursor(&qd.arrow); theErr = TrackDrag(theDrag, theEvent, theRgn); DisposeDrag(theDrag); } } if (theRgn) DisposeRgn(theRgn); if (tempRgn) DisposeRgn(tempRgn); } else if (FrontWindow() != gStatWindow) SendMoveToFront(gStatWindow); } /* * DoStatsHelp(globalPt) * * Purpose: Pops up help for the statistics windoid; needed because it should be displayed even * if it's not "active" * Inputs: globalPt = point, in global coordinates, where the mouse is * Returns: nothing * */ void DoStatsHelp(Point globalPt) { static Boolean gLastWasGeneric = false; Boolean balloonUp = HMIsBalloon(); HMMessageRecord theRecord; short index = 1, line; ImageHandle theImage; Point tip = { 0, 0 }; WindowPtr theWindow; Rect aRect; if ((balloonUp && !gLastWasGeneric) || gInBackground) return; PushPort(); MySetPort((CGrafPtr)gStatWindow); GlobalToLocal(&globalPt); for (theWindow = GetFirstWindow(); theWindow && !(theImage = FindImage(theWindow)); theWindow = NextWindow(theWindow)); if (theImage && IsAboutBox(theImage)) index = 2; else if (gThePrefs.statsZoomed) { index = 3; for (line = 0; line <= (strFreeMemory - strFileName); line++) if (PtInRect(globalPt, &gStatRect[line])) { index = line + 4; break; } } else index = 1; if (gLastWasGeneric && index <= 3 && balloonUp) { PopPort(); return; } if (gLastWasGeneric = (index <= 3)) aRect = gStatWindow->portRect; else aRect = gStatRect[line]; if (balloonUp) HMRemoveBalloon(); if (HMExtractHelpMsg(kHMRectListResType, rStatWindow, index, kHMEnabledItem, &theRecord) == noErr) { tip.h = aRect.right; tip.v = aRect.top + Height(&aRect) / 2; LocalToGlobal(&tip); GlobalRect(&aRect, gStatWindow); HMShowBalloon(&theRecord, tip, &aRect, nil, 0, 0, kHMRegularWindow); } PopPort(); } \ No newline at end of file diff --git a/Source/C/TIFF.c b/Source/C/TIFF.c new file mode 100644 index 0000000..edfc434 --- /dev/null +++ b/Source/C/TIFF.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ //===================================================================================== // Generic includes for Macintosh headers //===================================================================================== #if THINK_C #include "THINK.Header" #include #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif //===================================================================================== // Includes specific to this module //===================================================================================== #include "TIFF.h" #include "TIFFTables.c" //===================================================================================== // TIFFPrivates: private data structure for TIFF images, maintained for each image. //===================================================================================== typedef struct TIFFPrivates TIFFPrivates, *TIFFPrivatesPtr, **TIFFPrivatesHandle; typedef (*ExtractProcPtr)(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); struct TIFFPrivates { Boolean offsetsAreShort; // flag: true if the strip offsets are shorts ushort photoInt; // photometric interpretation ushort compression; // compression method used ushort bitsPerSample; // number of bits per sample (must be same for all) ushort samplesPerPixel; // number of samples per pixel (only first 3 count) ushort depth; // calculated depth of the image ulong height, width; // size of the image ulong rowsPerStrip; // number of rows per strip ulong stripOffsetsList; // offset in data of list of strip offsets ulong colorTableOffset; // offset of the color table in the file CTabHandle decompColors; // color table to be used in decompression Boolean invert; // flag: true to invert all outgoing bytes Boolean prediction; // flag: true if we are decoding with prediction ExtractProcPtr extract; // pointer to extract function }; //===================================================================================== // Constants specific to this module //===================================================================================== enum { tagBitsPerSample = 0x102, // [short], default = 1 tagColorMap = 0x140, // [short], required for palette images tagCompression = 0x103, // short, default = 1 compNone = 1, compModCCITT3 = 2, compCCITT3 = 3, compLZW = 5, compPackBits = 32773, tagFillOrder = 0x10a, // fill order, must be 1 tagImageDescription = 0x13c, // [ASCII], optional tagImageLength = 0x101, // short or long, required tagImageWidth = 0x100, // short or long, required tagPhotometricInterpretation = 0x106,// short, required photoWhiteIsZero = 0, photoBlackIsZero = 1, photoRGB = 2, photoPalette = 3, tagOrientation = 0x112, // orientation, must be 1 tagPlanarConfiguration = 0x11c, // planar configuration, must be 1 tagPredictor = 0x13d, // predictor, must be 1 tagRowsPerStrip = 0x116, // short or long, default = 16777215 tagSamplesPerPixel = 0x115, // short, default = 1 tagStripOffsets = 0x111 // [short or long], required }; enum { typeByte = 1, typeASCII = 2, typeShort = 3, typeLong = 4, typeRational = 5 }; enum { errAllDone = 1 }; //===================================================================================== // Global variables local to this module //===================================================================================== static TIFFPrivates gTIFFDefaults = { false, // offsets are long 0, // no photometric interpretation default compNone, // no compression 1, // 1 bit per sample 1, // 1 sample per pixel 1, // depth is 1 bit 0, 0, // height and width are 0 0, // 0 rows per strip (fixed at runtime for def.) 0, // a nil strip offsets list 0, // and a nil color table offset nil, // nil handle for the image color table false, // don't invert false, // no prediction nil // no default decoding function }; static long gTotalLines, gCurrentLines; static uchar *gStack, *gTree; //===================================================================================== // Prototypes for functions local to this module //===================================================================================== static OSErr ProcessTag(uchar *dataStart, ulong offset, ImageHandle theImage); static CTabHandle MakeBlackAndWhiteCTable(ulong pi, short depth); static CTabHandle ExtractColorTable(uchar *dataStart, ulong offset, short depth); static OSErr SetUpCompression(TIFFPrivatesHandle privates, ImageHandle theImage); static OSErr DecompressTIFFImage(uchar *dataStart, TIFFPrivatesHandle privates, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length); static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow); static OSErr ExtractUncompressed(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); static OSErr ExtractCCITT3(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); static OSErr ExtractPackBits(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); static OSErr ExtractLZW(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); static OSErr ExtractUncompressedRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); static OSErr ExtractPackBitsRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); static OSErr ExtractLZWRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates); static ulong GetOneUnsigned(uchar *data, long offset); static ulong GetByte(uchar *data, long offset); static ulong GetShort(uchar *data, long offset); static ulong GetLong(uchar *data, long offset); static Fixed GetRational(uchar *data, long offset); //===================================================================================== // Boolean idTIFF(uchar *theData, long theSize) //===================================================================================== // Examines the given data and attempts to identify it as a TIFF image. //===================================================================================== extern Boolean idTIFF(uchar *theData, long theSize, short refNum, FSSpec *theSpec) { #if applec #pragma unused(refNum, theSpec) #endif return (theSize > 4 && (theData[0] == 'I' && theData[1] == 'I' && theData[2] == 42 && theData[3] == 0) || (theData[0] == 'M' && theData[1] == 'M' && theData[2] == 0 && theData[3] == 42)); } //===================================================================================== // OSErr OpenTIFF(ImageHandle theImage) //===================================================================================== // Initializes the image record for a TIFF image; note that since we are a simple // baseline TIFF reader, we only read the first set of tags. //===================================================================================== extern OSErr OpenTIFF(ImageHandle theImage) { long theLen = GetHandleSize((*theImage)->data); char hState = HGetState((*theImage)->data); TIFFPrivatesHandle privates; OSErr theErr = noErr; ulong offset, count; uchar *dataStart; theErr = PtrToHand(&gTIFFDefaults, (Handle *)&privates, sizeof(TIFFPrivates)); if (theErr != noErr) return theErr; (*theImage)->privateData = (Handle)privates; HLock((*theImage)->data); dataStart = (uchar *)*(*theImage)->data; offset = GetLong(dataStart, 4); count = GetShort(dataStart, offset), offset += 2; while (count-- && theErr == noErr) { theErr = ProcessTag(dataStart, offset, theImage); offset += 12; if (offset > theLen) theErr = codecBadDataErr; } if (theErr == noErr) { if ((*privates)->photoInt == photoWhiteIsZero || (*privates)->photoInt == photoBlackIsZero) { (*privates)->depth = (*theImage)->depth = (*privates)->bitsPerSample; if ((*theImage)->depth != 1 && (*theImage)->depth != 4 && (*theImage)->depth != 8) gIntError = errBadTIFFExtension, theErr = codecBadDataErr; else if ((*theImage)->depth == 1) (*privates)->invert = ((*privates)->photoInt == photoBlackIsZero); else { (*privates)->decompColors = MakeBlackAndWhiteCTable((*privates)->photoInt, (*theImage)->depth); if (!(*privates)->decompColors) theErr = memFullErr; } } else if ((*privates)->photoInt == photoRGB) { if ((*privates)->bitsPerSample != 8) gIntError = errBadTIFFExtension, theErr = codecBadDataErr; (*privates)->depth = (*theImage)->depth = 32; } else if ((*privates)->photoInt == photoPalette) { (*privates)->depth = (*theImage)->depth = (*privates)->bitsPerSample; if ((*theImage)->depth != 4 && (*theImage)->depth != 8) gIntError = errBadTIFFExtension, theErr = codecBadDataErr; if (!(*privates)->colorTableOffset) theErr = codecBadDataErr; (*privates)->decompColors = ExtractColorTable(dataStart, (*privates)->colorTableOffset, (*theImage)->depth); if (!(*privates)->decompColors) theErr = memFullErr; } else gIntError = errBadTIFFExtension, theErr = codecBadDataErr; if (!(*theImage)->depth) theErr = codecBadDataErr; if (!(*privates)->stripOffsetsList) gIntError = errBadTIFFExtension, theErr = codecBadDataErr; if ((*privates)->compression == compModCCITT3 && (*theImage)->depth != 1) theErr = codecBadDataErr; if (!Width(&(*theImage)->grect) || !Height(&(*theImage)->grect)) theErr = codecBadDataErr; if (theErr == noErr) theErr = SetUpCompression(privates, theImage); if (!(*privates)->rowsPerStrip || (*privates)->rowsPerStrip > (*privates)->height) (*privates)->rowsPerStrip = (*privates)->height; if ((*privates)->decompColors) (*theImage)->ipalette = NewPalette(256, (*privates)->decompColors, pmTolerant, 0); (*theImage)->qrect = (*theImage)->crect = (*theImage)->grect; } HSetState((*theImage)->data, hState); return theErr; } //===================================================================================== // OSErr DrawTIFF(Handle theHandle, JVDrawParamsHandle theParams) //===================================================================================== // Draws a TIFF image into the specified GWorld, from the srcRect into the dstRect, // clipping as dstRgn specifies. //===================================================================================== extern OSErr DrawTIFF(Handle theHandle, JVDrawParamsHandle theParams) { TIFFPrivatesHandle privates = (TIFFPrivatesHandle)(*theParams)->privateData; NestedProgress theProgress = (*theParams)->progress; char hState = HGetState(theHandle); Handle lzwDataHandle = nil; OSErr theErr = noErr; GWorldPtr theGWorld; uchar *dataStart; if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00000000L, theProgress.prog.progressRefCon); HLockHi(theHandle); if ((*privates)->compression == compLZW) { lzwDataHandle = NewHandleClear(4096 + 4096 * 4); if (!lzwDataHandle) lzwDataHandle = TempNewHandle(4096 + 4096 * 4, &theErr); if (lzwDataHandle && theErr == noErr) { HLockHi(lzwDataHandle); gStack = (uchar *)StripAddress(*lzwDataHandle); gTree = gStack + 4096; } } if (theErr == noErr) { dataStart = (uchar *)StripAddress(*theHandle); theGWorld = NewTempGWorld((*privates)->width, (*privates)->height, (*privates)->depth, (*privates)->decompColors); if (theGWorld) { theErr = DecompressTIFFImage(dataStart, privates, GetGWorldPixMap(theGWorld), (ICMProgressProcRecordPtr)&theProgress, GetHandleSize(theHandle)); if ((*theParams)->progress.aborted) theErr = codecAbortErr; DisposeGWorld(theGWorld); } else gIntError = errNoDrawMemory, theErr = memFullErr; } if (lzwDataHandle) DisposeHandle(lzwDataHandle); HSetState(theHandle, hState); if (theProgress.prog.progressProc) CallICMProgressProc(theProgress.prog.progressProc, codecProgressUpdatePercent, 0x00010000L, theProgress.prog.progressRefCon); return theErr; } //===================================================================================== // OSErr CloneTIFF(ImageHandle origImage, ImageHandle newImage) //===================================================================================== // Called when an image is cloned, to give us a chance to duplicate any secondary // storage. //===================================================================================== extern OSErr CloneTIFF(ImageHandle origImage, ImageHandle newImage) { TIFFPrivatesHandle origPrivates = (TIFFPrivatesHandle)(*origImage)->privateData; TIFFPrivatesHandle newPrivates = (TIFFPrivatesHandle)(*newImage)->privateData; CTabHandle theColors; OSErr theErr; if (origPrivates && newPrivates) { if (theColors = (*origPrivates)->decompColors) { theErr = HandToHand((Handle *)&theColors); (*newPrivates)->decompColors = theColors; } } return theErr; } //===================================================================================== // OSErr CloseTIFF(ImageHandle theImage) //===================================================================================== // Called before the image is disposed, to get rid of any secondary storage we // allocated on open. //===================================================================================== extern OSErr CloseTIFF(ImageHandle theImage) { TIFFPrivatesHandle privates = (TIFFPrivatesHandle)(*theImage)->privateData; if (privates) if ((*privates)->decompColors) DisposeHandle((Handle)(*privates)->decompColors); return noErr; } //===================================================================================== // OSErr ProcessTag(uchar *dataStart, ulong offset, ImageHandle theImage) //===================================================================================== // Process the TIFF tag pointed to by offset. If it's something we recognize, we // attempt to fill in the appropriate data structures in the image record, or in the // attached TIFF private data. //===================================================================================== static OSErr ProcessTag(uchar *dataStart, ulong offset, ImageHandle theImage) { TIFFPrivatesHandle privates = (TIFFPrivatesHandle)(*theImage)->privateData; ushort tag = GetShort(dataStart, offset); OSErr theErr = noErr; ulong data; switch (tag) { case tagImageWidth: (*privates)->width = (*theImage)->grect.right = GetOneUnsigned(dataStart, offset + 2); break; case tagImageLength: (*privates)->height = (*theImage)->grect.bottom = GetOneUnsigned(dataStart, offset + 2); break; case tagBitsPerSample: (*privates)->bitsPerSample = GetOneUnsigned(dataStart, offset + 2); break; case tagCompression: (*privates)->compression = GetOneUnsigned(dataStart, offset + 2); break; case tagPhotometricInterpretation: (*privates)->photoInt = GetOneUnsigned(dataStart, offset + 2); break; case tagStripOffsets: data = GetShort(dataStart, offset + 2); if (data == typeShort) (*privates)->offsetsAreShort = true; else if (data == typeLong) (*privates)->offsetsAreShort = false; else return codecBadDataErr; data = GetLong(dataStart, offset + 4); if (data == 1 || (data == 2 && (*privates)->offsetsAreShort)) (*privates)->stripOffsetsList = offset + 8; else (*privates)->stripOffsetsList = GetLong(dataStart, offset + 8); break; case tagSamplesPerPixel: (*privates)->samplesPerPixel = GetOneUnsigned(dataStart, offset + 2); break; case tagRowsPerStrip: (*privates)->rowsPerStrip = GetOneUnsigned(dataStart, offset + 2); break; case tagImageDescription: if (GetShort(dataStart, offset + 2) != typeASCII) return codecBadDataErr; data = GetLong(dataStart, offset + 4); if (data <= 4) offset += 8; else offset = GetLong(dataStart, offset + 8); if (!(*theImage)->comments) theErr = PtrToHand(dataStart + offset, &(*theImage)->comments, data - 1); break; case tagColorMap: if (GetShort(dataStart, offset + 2) != typeShort) return codecBadDataErr; (*privates)->colorTableOffset = offset + 4; break; case tagPredictor: data = GetOneUnsigned(dataStart, offset + 2); if (data == 1) (*privates)->prediction = false; else if (data == 2) (*privates)->prediction = true; else gIntError = errBadTIFFExtension, theErr = codecBadDataErr; break; case tagFillOrder: case tagOrientation: case tagPlanarConfiguration: if (GetOneUnsigned(dataStart, offset + 2) != 1) gIntError = errBadTIFFExtension, theErr = codecBadDataErr; } return theErr; } //===================================================================================== // CTabHandle MakeBlackAndWhiteCTable(ulong pi, short depth) //===================================================================================== // Creates a black & white/grayscale color table, according to the given // photometric interpretation. If pi says that white is zero, we go from brightest to // darkest in even steps for the entire color table size; otherwise, we go from // darkest to brightest. //===================================================================================== static CTabHandle MakeBlackAndWhiteCTable(ulong pi, short depth) { ushort color, count = (1L << depth), i; CTabHandle theColors; theColors = (CTabHandle)NewHandleClear(sizeof(ColorTable) + (count - 1) * sizeof(ColorSpec)); if (theColors) { (*theColors)->ctSeed = GetCTSeed(); (*theColors)->ctFlags = 0x8000; (*theColors)->ctSize = count - 1; for (i = 0; i < count; i++) { color = (ulong)i * 65535L / (long)(count - 1); if (pi == photoWhiteIsZero) color = 65535L - color; (*theColors)->ctTable[i].rgb.red = (*theColors)->ctTable[i].rgb.green = (*theColors)->ctTable[i].rgb.blue = color; } } return theColors; } //===================================================================================== // CTabHandle ExtractColorTable(uchar *dataStart, ulong offset, short depth) //===================================================================================== // Extracts the included TIFF color table from the data at the given offset. //===================================================================================== static CTabHandle ExtractColorTable(uchar *dataStart, ulong offset, short depth) { ulong count = GetLong(dataStart, offset) / 3, size = (1L << depth), i; CTabHandle theColors; if ((depth != 4 && depth != 8) || count > size) return nil; theColors = (CTabHandle)NewHandleClear(sizeof(ColorTable) + (size - 1) * sizeof(ColorSpec)); offset = GetLong(dataStart, offset + 4); if (theColors) { (*theColors)->ctSeed = GetCTSeed(); (*theColors)->ctFlags = 0x8000; (*theColors)->ctSize = size; for (i = 0; i < count; i++) (*theColors)->ctTable[i].rgb.red = GetShort(dataStart, offset), offset += 2; for (i = 0; i < count; i++) (*theColors)->ctTable[i].rgb.green = GetShort(dataStart, offset), offset += 2; for (i = 0; i < count; i++) (*theColors)->ctTable[i].rgb.blue = GetShort(dataStart, offset), offset += 2; } return theColors; } //===================================================================================== // OSErr SetUpCompression(TIFFPrivatesHandle privates, ImageHandle theImage) //===================================================================================== // Sets up the compression parameters for the TIFF image. //===================================================================================== static OSErr SetUpCompression(TIFFPrivatesHandle privates, ImageHandle theImage) { OSErr theErr = noErr; switch ((*privates)->compression) { case compNone: (*theImage)->compression = 0; BlockMove(gString[strUncompressed], (*theImage)->compressionDesc, *gString[strUncompressed] + 1); (*privates)->extract = ((*privates)->samplesPerPixel == 1) ? (ExtractProcPtr)ExtractUncompressed : (ExtractProcPtr)ExtractUncompressedRGB; break; // case compCCITT3: case compModCCITT3: (*theImage)->compression = kCCITTCompression; BlockMove(gString[strCCITT3], (*theImage)->compressionDesc, *gString[strCCITT3] + 1); (*privates)->extract = (ExtractProcPtr)ExtractCCITT3; break; case compPackBits: (*theImage)->compression = kPackBitsCompression; BlockMove(gString[strPackBits], (*theImage)->compressionDesc, *gString[strPackBits] + 1); (*privates)->extract = ((*privates)->samplesPerPixel == 1) ? (ExtractProcPtr)ExtractPackBits : (ExtractProcPtr)ExtractPackBitsRGB; break; case compLZW: (*theImage)->compression = kLZWCompression; if ((*privates)->prediction) BlockMove(gString[strLZWPredict], (*theImage)->compressionDesc, *gString[strLZWPredict] + 1); else BlockMove(gString[strLZW], (*theImage)->compressionDesc, *gString[strLZW] + 1); (*privates)->extract = ((*privates)->samplesPerPixel == 1) ? (ExtractProcPtr)ExtractLZW : (ExtractProcPtr)ExtractLZWRGB; break; default: gIntError = errBadTIFFExtension, theErr = codecBadDataErr; break; } return theErr; } //===================================================================================== // OSErr DecompressTIFFImage(uchar *dataStart, TIFFPrivatesHandle privates, // PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length) //===================================================================================== // Oversees the decompression of a TIFF image, handling strip decoding and banding, and // calling the appropriate function to perform the actual decompression. //===================================================================================== static OSErr DecompressTIFFImage(uchar *dataStart, TIFFPrivatesHandle privates, PixMapHandle dstPixMap, ICMProgressProcRecordPtr prog, Size length) { ulong numStrips = (((*privates)->height + (*privates)->rowsPerStrip - 1) / (*privates)->rowsPerStrip); ulong row, strip, offset, offsetOffset = (*privates)->stripOffsetsList; uchar *ptr, *rowStart, *dataEnd = dataStart + length; char pState = GetPixelsState(dstPixMap); RgnHandle dstRgn = qd.thePort->visRgn; ulong totalRows = 0, bandRow = 0; char mmuMode = true32b; OSErr theErr = noErr; LockPixels(dstPixMap); rowStart = (uchar *)GetPixBaseAddr(dstPixMap); for (strip = 0; strip < numStrips && totalRows < (*privates)->height; strip++) { if ((*privates)->offsetsAreShort) offset = GetShort(dataStart, offsetOffset), offsetOffset += 2; else offset = GetLong(dataStart, offsetOffset), offsetOffset += 4; ptr = dataStart + offset; for (row = 0; row < (*privates)->rowsPerStrip && totalRows < (*privates)->height; row++) { if (ptr < dataStart || ptr > dataEnd) { theErr = codecBadDataErr; break; } SwapMMUMode(&mmuMode); if (row == 0) (*privates)->extract(nil, nil, privates); theErr = (*privates)->extract(&ptr, rowStart, privates); SwapMMUMode(&mmuMode); rowStart += ((*dstPixMap)->rowBytes & 0x3fff); if (theErr == noErr && !(++totalRows & 63) && prog->progressProc) theErr = (OSErr)CallICMProgressProc(prog->progressProc, codecProgressUpdatePercent, FixRatio(totalRows, (*privates)->height), prog->progressRefCon); if (++bandRow == Height(&(*dstPixMap)->bounds)) { CopyPixMapToDestination(dstPixMap, totalRows - bandRow); bandRow = 0; rowStart = (uchar *)GetPixBaseAddr(dstPixMap); } if (theErr != noErr) break; } if (theErr != noErr) break; } if (theErr == errAllDone) theErr = noErr; if (theErr == noErr && bandRow) CopyPixMapToDestination(dstPixMap, totalRows - bandRow); SetPixelsState(dstPixMap, pState); return theErr; } //===================================================================================== // void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) //===================================================================================== // Copies the band contained in srcPixMap to the destination, offset from the top by // startRow. //===================================================================================== static void CopyPixMapToDestination(PixMapHandle srcPixMap, short startRow) { Rect srcRect = (*srcPixMap)->bounds, dstRect = (*srcPixMap)->bounds; PixMapHandle dstPixMap = GetGWorldPixMap((CGrafPtr)qd.thePort); char srcState = HGetState((Handle)srcPixMap); char dstState = HGetState((Handle)dstPixMap); OffsetRect(&dstRect, 0, startRow); HLock((Handle)srcPixMap); HLock((Handle)dstPixMap); CopyBits((BitMap *)*srcPixMap, (BitMap *)*dstPixMap, &srcRect, &dstRect, srcCopy + ditherCopy, qd.thePort->visRgn); HSetState((Handle)dstPixMap, dstState); HSetState((Handle)srcPixMap, srcState); } //===================================================================================== // OSErr ExtractUncompressed(uchar **srcData, uchar *dstData, // TIFFPrivatesHandle privates) //===================================================================================== // Pulls out a row of uncompressed 1, 4, or 8 bit data. //===================================================================================== static OSErr ExtractUncompressed(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) { ulong bytes = ((*privates)->width * (*privates)->bitsPerSample + 7) / 8L; uchar *src = *srcData; if (srcData == nil && dstData == nil) return noErr; if ((*privates)->invert) while (bytes--) *dstData++ = ~(*src++); else while (bytes--) *dstData++ = *src++; *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractUncompressedRGB(uchar **srcData, uchar *dstData, // TIFFPrivatesHandle privates) //===================================================================================== // Pulls out a row of uncompressed RGB data, skipping the alpha channel in the // destination and ignoring anything other than the first 3 samples for each pixel. //===================================================================================== static OSErr ExtractUncompressedRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) { ushort extra = (*privates)->samplesPerPixel - 3; ulong col = (*privates)->width; uchar *src = *srcData; if (srcData == nil && dstData == nil) return noErr; while (col--) { dstData++, *dstData++ = *src++, *dstData++ = *src++, *dstData++ = *src++; src += extra; } *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractCCITT3(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) //===================================================================================== // Pulls out a row of modified Huffman CCITT-compressed 1-bit data. //===================================================================================== static OSErr ExtractCCITT3(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) { static ushort gBitBuffer, gBitsInBuffer; Boolean white = true, nextWhite = true, invert = ((*privates)->invert) ? true : false; Boolean wasTerminating = true; uchar *src = *srcData, dstMask = 0xff; long width = (*privates)->width; short count, dstBits = 8; ExtractTable *code; if (srcData == nil && dstData == nil) { gBitBuffer = gBitsInBuffer = 0; return noErr; } while (width || !wasTerminating) { if (gBitsInBuffer < 8) { gBitBuffer |= (ushort)*src++ << (8 - gBitsInBuffer); gBitsInBuffer += 8; } code = (white) ? &whiteExtract[gBitBuffer >> 8] : &blackExtract[gBitBuffer >> 8]; if (code->leftover < 0) { gBitBuffer <<= 8; gBitsInBuffer -= 8; if (gBitsInBuffer < 8) { gBitBuffer |= (ushort)*src++ << (8 - gBitsInBuffer); gBitsInBuffer += 8; } count = -code->leftover; code = (white) ? &whiteExtract[code->count + (gBitBuffer >> (16 - count))] : &blackExtract[code->count + (gBitBuffer >> (16 - count))]; gBitBuffer <<= (count - code->leftover); gBitsInBuffer -= (count - code->leftover); } else { gBitBuffer <<= (8 - code->leftover); gBitsInBuffer -= (8 - code->leftover); } count = code->count; if (count == -1) { return codecBadDataErr; } else if (count == -2) continue; if ((width -= count) < 0) { return codecBadDataErr; } if (wasTerminating = count < 64) nextWhite = !white; if (count >= dstBits) { if (white ^ invert) *dstData++ &= ~dstMask; else *dstData++ |= dstMask; count -= dstBits; while (count >= 8) { *dstData++ = (white ^ invert) ? 0 : 0xff; count -= 8; } dstBits = 8; dstMask = 0xff; } if (count) { if (white ^ invert) *dstData &= ~(dstMask ^ (dstMask >> count)); else *dstData |= (dstMask ^ (dstMask >> count)); dstMask >>= count; dstBits -= count; } white = nextWhite; } if ((*privates)->compression == compModCCITT3) { while (gBitsInBuffer >= 8) src--, gBitsInBuffer -= 8; gBitsInBuffer = gBitBuffer = 0; } *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractPackBits(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) //===================================================================================== // Pulls out a row of PackBits-compressed 1, 4, or 8 bit data. //===================================================================================== static OSErr ExtractPackBits(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) { long bytes = ((*privates)->width * (*privates)->bitsPerSample + 7) / 8L; Boolean invert = (*privates)->invert; uchar *src = *srcData, value; signed short count; if (srcData == nil && dstData == nil) return noErr; while (bytes) { count = (signed char)*src++; if (count < 0) { value = (invert) ? ~(*src++) : *src++; count = -count + 1; if ((bytes -= count) < 0) return codecBadDataErr; while (count--) *dstData++ = value; } else { count++; if ((bytes -= count) < 0) return codecBadDataErr; if (invert) while (count--) *dstData++ = ~(*src++); else while (count--) *dstData++ = *src++; } } *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractPackBitsRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) //===================================================================================== // Pulls out a row of PackBits-compressed RGB data, skipping the alpha channel in the // destination and ignoring anything other than the first 3 samples for each pixel. //===================================================================================== static OSErr ExtractPackBitsRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) { long bytes = ((*privates)->width * (*privates)->bitsPerSample + 7) / 8L; ushort extra = (*privates)->samplesPerPixel - 3, sample = 0; Boolean invert = (*privates)->invert; uchar *src = *srcData, value; signed short count; if (srcData == nil && dstData == nil) return noErr; bytes *= (*privates)->samplesPerPixel; while (bytes) { count = (signed char)*src++; if (count < 0) { value = *src++; count = -count + 1; if ((bytes -= count) < 0) return codecBadDataErr; while (count--) { if (!sample) dstData++; if (sample < 3) *dstData++ = value; if (++sample == (*privates)->samplesPerPixel) sample = 0; } } else { count++; if ((bytes -= count) < 0) return codecBadDataErr; while (count--) { if (!sample) dstData++; if (sample < 3) *dstData++ = *src++; if (++sample == (*privates)->samplesPerPixel) sample = 0; } } } *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractLZW(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) //===================================================================================== // Pulls out a row of LZW-compressed 1, 4, or 8 bit data. //===================================================================================== static OSErr ExtractLZW(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) { #define gClearCode 256 #define gEndCode 257 static ushort gTreeSize, gCodeSize, gFirstCode, gLastCode; static ulong gBitBuffer, gBitsInBuffer; static uchar *gStackPtr; ushort *parent = (ushort *)gTree; uchar *code = (uchar *)(parent + 4096); short i, j, currentCode, oldCode; ulong bytes = ((*privates)->width * (*privates)->bitsPerSample + 7) / 8L; uchar *src; if (srcData == nil && dstData == nil) { gStackPtr = gStack; gCodeSize = 9; gBitsInBuffer = gBitBuffer = 0; gTreeSize = gEndCode + 1; return noErr; } src = *srcData; for (i = 0; i < bytes; i++) { if (gStackPtr != gStack) { if ((*privates)->prediction && i) *dstData = dstData[-1] + *(--gStackPtr), dstData++; else *dstData++ = *(--gStackPtr); continue; } while (gCodeSize > gBitsInBuffer) { gBitBuffer |= (ulong)*src++ << (24 - gBitsInBuffer); gBitsInBuffer += 8; } currentCode = gBitBuffer >> (32 - gCodeSize); gBitBuffer <<= gCodeSize; gBitsInBuffer -= gCodeSize; if (currentCode == gEndCode) return errAllDone; else if (currentCode == gClearCode) { gCodeSize = 9; gTreeSize = gEndCode + 1; do { while (gCodeSize > gBitsInBuffer) { gBitBuffer |= (ulong)*src++ << (24 - gBitsInBuffer); gBitsInBuffer += 8; } currentCode = gBitBuffer >> (32 - gCodeSize); gBitBuffer <<= gCodeSize; gBitsInBuffer -= gCodeSize; } while (currentCode == gClearCode); if ((*privates)->prediction && i) *dstData = dstData[-1] + currentCode, dstData++; else *dstData++ = currentCode; gFirstCode = gLastCode = currentCode; continue; } oldCode = currentCode; if (currentCode > gTreeSize) return codecBadDataErr; else if (currentCode == gTreeSize) { *gStackPtr++ = gFirstCode; currentCode = gLastCode; } for (j = currentCode; j >= gClearCode; j = parent[j]) *gStackPtr++ = code[j]; if ((*privates)->prediction && i) *dstData = dstData[-1] + j, dstData++; else *dstData++ = j; gFirstCode = j; if (gTreeSize != 4096) { code[gTreeSize] = gFirstCode; parent[gTreeSize] = gLastCode; if ((++gTreeSize >= ((1 << gCodeSize) - 1)) && (gCodeSize != 12)) gCodeSize++; } gLastCode = oldCode; } *srcData = src; return noErr; } //===================================================================================== // OSErr ExtractLZWRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) //===================================================================================== // Pulls out a row of LZW-compressed RGB data, skipping the alpha channel in the // destination and ignoring anything other than the first 3 samples for each pixel. //===================================================================================== static OSErr ExtractLZWRGB(uchar **srcData, uchar *dstData, TIFFPrivatesHandle privates) { #define gClearCode 256 #define gEndCode 257 static ushort gTreeSize, gCodeSize, gFirstCode, gLastCode; static ulong gBitBuffer, gBitsInBuffer; static uchar *gStackPtr; ulong bytes = ((*privates)->width * (*privates)->bitsPerSample + 7) / 8L; ushort extra = 0, storeCount = 0, extraCount = 0, total; ushort *parent = (ushort *)gTree; uchar *code = (uchar *)(parent + 4096); short i, j, currentCode, oldCode; uchar *src; if (srcData == nil && dstData == nil) { gStackPtr = gStack; gCodeSize = 9; gBitsInBuffer = gBitBuffer = 0; gTreeSize = gEndCode + 1; return noErr; } bytes *= total = (*privates)->samplesPerPixel; extraCount = extra = total - 3; storeCount = 3; src = *srcData; for (i = 0; i < bytes; i++) { if (storeCount == 3) dstData++; if (gStackPtr != gStack) { if (storeCount) { if ((*privates)->prediction && i >= total) *dstData = dstData[-4] + *(--gStackPtr), dstData++; else *dstData++ = *(--gStackPtr); if (!--storeCount && !extraCount) storeCount = 3; } else { --gStackPtr; if (!--extraCount) storeCount = 3, extraCount = extra; } continue; } while (gCodeSize > gBitsInBuffer) { gBitBuffer |= (ulong)*src++ << (24 - gBitsInBuffer); gBitsInBuffer += 8; } currentCode = gBitBuffer >> (32 - gCodeSize); gBitBuffer <<= gCodeSize; gBitsInBuffer -= gCodeSize; if (currentCode == gEndCode) return errAllDone; else if (currentCode == gClearCode) { gCodeSize = 9; gTreeSize = gEndCode + 1; do { while (gCodeSize > gBitsInBuffer) { gBitBuffer |= (ulong)*src++ << (24 - gBitsInBuffer); gBitsInBuffer += 8; } currentCode = gBitBuffer >> (32 - gCodeSize); gBitBuffer <<= gCodeSize; gBitsInBuffer -= gCodeSize; } while (currentCode == gClearCode); if (storeCount) { if ((*privates)->prediction && i >= total) *dstData = dstData[-4] + currentCode, dstData++; else *dstData++ = currentCode; if (!--storeCount && !extraCount) storeCount = 3; } else if (!--extraCount) storeCount = 3, extraCount = extra; gFirstCode = gLastCode = currentCode; continue; } oldCode = currentCode; if (currentCode > gTreeSize) return codecBadDataErr; else if (currentCode == gTreeSize) { *gStackPtr++ = gFirstCode; currentCode = gLastCode; } for (j = currentCode; j >= gClearCode; j = parent[j]) *gStackPtr++ = code[j]; if (storeCount) { if ((*privates)->prediction && i >= total) *dstData = dstData[-4] + j, dstData++; else *dstData++ = j; if (!--storeCount && !extraCount) storeCount = 3; } else if (!--extraCount) storeCount = 3, extraCount = extra; gFirstCode = j; if (gTreeSize != 4096) { code[gTreeSize] = gFirstCode; parent[gTreeSize] = gLastCode; if ((++gTreeSize >= ((1 << gCodeSize) - 1)) && (gCodeSize != 12)) gCodeSize++; } gLastCode = oldCode; } *srcData = src; return noErr; } //===================================================================================== // ulong GetOneUnsigned(uchar *data, long offset) //===================================================================================== // Extracts an unsigned value from the data at the given offset. //===================================================================================== static ulong GetOneUnsigned(uchar *data, long offset) { ushort type = GetShort(data, offset); ulong count = GetLong(data, offset + 2); if (type == typeByte) { if (count <= 4) return GetByte(data, offset + 6); else return GetByte(data, GetLong(data, offset + 6)); } else if (type == typeShort) { if (count <= 2) return GetShort(data, offset + 6); else return GetShort(data, GetLong(data, offset + 6)); } else if (type == typeLong) { if (count == 1) return GetLong(data, offset + 6); else return GetLong(data, GetLong(data, offset + 6)); } return 0; } //===================================================================================== // ulong GetByte(uchar *data, long offset) //===================================================================================== // Extracts an unsigned byte from the data at the given offset. //===================================================================================== static ulong GetByte(uchar *data, long offset) { return data[offset]; } //===================================================================================== // ulong GetShort(uchar *data, long offset) //===================================================================================== // Extracts an unsigned byte from the data at the given offset. //===================================================================================== static ulong GetShort(uchar *data, long offset) { if (*data == 'I') return (ulong)data[offset] + ((ulong)data[offset + 1] << 8); else return ((ulong)data[offset] << 8) + (ulong)data[offset + 1]; } //===================================================================================== // ulong GetLong(uchar *data, long offset) //===================================================================================== // Extracts an unsigned byte from the data at the given offset. //===================================================================================== static ulong GetLong(uchar *data, long offset) { if (*data == 'I') return (ulong)data[offset] + ((ulong)data[offset + 1] << 8) + ((ulong)data[offset + 2] << 16) + ((ulong)data[offset + 3] << 24); else return ((ulong)data[offset] << 24) + ((ulong)data[offset + 1] << 16) + ((ulong)data[offset + 2] << 8) + (ulong)data[offset + 3]; } //===================================================================================== // Fixed GetRational(uchar *data, long offset) //===================================================================================== // Extracts a rational value from the data at the given offset, return it as a fixed- // point value. //===================================================================================== static Fixed GetRational(uchar *data, long offset) { ulong num = GetLong(data, offset); ulong den = GetLong(data, offset + 4); return FixRatio(num, den); } \ No newline at end of file diff --git a/Source/C/TIFFTables.c b/Source/C/TIFFTables.c new file mode 100644 index 0000000..ae50feb --- /dev/null +++ b/Source/C/TIFFTables.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ typedef struct ExtractTable { signed char leftover; signed short count; } ExtractTable; // format of table is: // // leftover count explanation // -------- ----- ----------- // 0-7 val val = # of bits to add; leftover = # of bits left out of 8 // <0 offset leftover = -# of bits needed; offset = address in table where // table of those bits begins // 0 -1 bad code // 0 -2 EOL code static ExtractTable whiteExtract[] = { -4, 256, // 00000000.... -4, 272, // 00000001.... (1792+) 0, 29, // 00000010 0, 30, // 00000011 0, 45, // 00000100 0, 46, // 00000101 1, 22, // 0000011/0 1, 22, // 0000011/1 1, 23, // 0000100/0 1, 23, // 0000100/1 0, 47, // 00001010 0, 48, // 00001011 2, 13, // 000011/00 2, 13, // 000011/01 2, 13, // 000011/10 2, 13, // 000011/11 1, 20, // 0001000/0 1, 20, // 0001000/1 0, 33, // 00010010 0, 34, // 00010011 0, 35, // 00010100 0, 36, // 00010101 0, 37, // 00010110 0, 38, // 00010111 1, 19, // 0001100/0 1, 19, // 0001100/1 0, 31, // 00011010 0, 32, // 00011011 2, 1, // 000111/00 2, 1, // 000111/01 2, 1, // 000111/10 2, 1, // 000111/11 2, 12, // 001000/00 2, 12, // 001000/01 2, 12, // 001000/10 2, 12, // 001000/11 0, 53, // 00100100 0, 54, // 00100101 1, 26, // 0010011/0 1, 26, // 0010011/1 0, 39, // 00101000 0, 40, // 00101001 0, 41, // 00101010 0, 42, // 00101011 0, 43, // 00101100 0, 44, // 00101101 1, 21, // 0010111/0 1, 21, // 0010111/1 1, 28, // 0011000/0 1, 28, // 0011000/1 0, 61, // 00110010 0, 62, // 00110011 0, 63, // 00110100 0, 0, // 00110101 0, 320, // 00110110 0, 384, // 00110111 3, 10, // 00111/000 3, 10, // 00111/001 3, 10, // 00111/010 3, 10, // 00111/011 3, 10, // 00111/100 3, 10, // 00111/101 3, 10, // 00111/110 3, 10, // 00111/111 3, 11, // 01000/000 3, 11, // 01000/001 3, 11, // 01000/010 3, 11, // 01000/011 3, 11, // 01000/100 3, 11, // 01000/101 3, 11, // 01000/110 3, 11, // 01000/111 1, 27, // 0100100/0 1, 27, // 0100100/1 0, 59, // 01001010 0, 60, // 01001011 -1, 288, // 01001100.... (1472/1536) -1, 290, // 01001101.... (1600/1728) 1, 18, // 0100111/0 1, 18, // 0100111/1 1, 24, // 0101000/0 1, 24, // 0101000/1 0, 49, // 01010010 0, 50, // 01010011 0, 51, // 01010100 0, 52, // 01010101 1, 25, // 0101011/0 1, 25, // 0101011/1 0, 55, // 01011000 0, 56, // 01011001 0, 57, // 01011010 0, 58, // 01011011 2, 192, // 010111/00 2, 192, // 010111/01 2, 192, // 010111/10 2, 192, // 010111/11 2, 1664, // 011000/00 2, 1664, // 011000/01 2, 1664, // 011000/10 2, 1664, // 011000/11 0, 448, // 01100100 0, 512, // 01100101 -1, 292, // 01100110.... (704/768) 0, 640, // 01100111 0, 576, // 01101000 -1, 294, // 01101001.... (832/896) -1, 296, // 01101010.... (960/1024) -1, 298, // 01101011.... (1088/1152) -1, 300, // 01101100.... (1216/1280) -1, 302, // 01101101.... (1344/1408) 1, 256, // 0110111/0 1, 256, // 0110111/1 4, 2, // 0111/0000 4, 2, // 0111/0001 4, 2, // 0111/0010 4, 2, // 0111/0011 4, 2, // 0111/0100 4, 2, // 0111/0101 4, 2, // 0111/0110 4, 2, // 0111/0111 4, 2, // 0111/1000 4, 2, // 0111/1001 4, 2, // 0111/1010 4, 2, // 0111/1011 4, 2, // 0111/1100 4, 2, // 0111/1101 4, 2, // 0111/1110 4, 2, // 0111/1111 4, 3, // 1000/0000 4, 3, // 1000/0001 4, 3, // 1000/0010 4, 3, // 1000/0011 4, 3, // 1000/0100 4, 3, // 1000/0101 4, 3, // 1000/0110 4, 3, // 1000/0111 4, 3, // 1000/1000 4, 3, // 1000/1001 4, 3, // 1000/1010 4, 3, // 1000/1011 4, 3, // 1000/1100 4, 3, // 1000/1101 4, 3, // 1000/1110 4, 3, // 1000/1111 3, 128, // 10010/000 3, 128, // 10010/001 3, 128, // 10010/010 3, 128, // 10010/011 3, 128, // 10010/100 3, 128, // 10010/101 3, 128, // 10010/110 3, 128, // 10010/111 3, 8, // 10011/000 3, 8, // 10011/001 3, 8, // 10011/010 3, 8, // 10011/011 3, 8, // 10011/100 3, 8, // 10011/101 3, 8, // 10011/110 3, 8, // 10011/111 3, 9, // 10100/000 3, 9, // 10100/001 3, 9, // 10100/010 3, 9, // 10100/011 3, 9, // 10100/100 3, 9, // 10100/101 3, 9, // 10100/110 3, 9, // 10100/111 2, 16, // 101010/00 2, 16, // 101010/01 2, 16, // 101010/10 2, 16, // 101010/11 2, 17, // 101011/00 2, 17, // 101011/01 2, 17, // 101011/10 2, 17, // 101011/11 4, 4, // 1011/0000 4, 4, // 1011/0001 4, 4, // 1011/0010 4, 4, // 1011/0011 4, 4, // 1011/0100 4, 4, // 1011/0101 4, 4, // 1011/0110 4, 4, // 1011/0111 4, 4, // 1011/1000 4, 4, // 1011/1001 4, 4, // 1011/1010 4, 4, // 1011/1011 4, 4, // 1011/1100 4, 4, // 1011/1101 4, 4, // 1011/1110 4, 4, // 1011/1111 4, 5, // 1100/0000 4, 5, // 1100/0001 4, 5, // 1100/0010 4, 5, // 1100/0011 4, 5, // 1100/0100 4, 5, // 1100/0101 4, 5, // 1100/0110 4, 5, // 1100/0111 4, 5, // 1100/1000 4, 5, // 1100/1001 4, 5, // 1100/1010 4, 5, // 1100/1011 4, 5, // 1100/1100 4, 5, // 1100/1101 4, 5, // 1100/1110 4, 5, // 1100/1111 2, 14, // 110100/00 2, 14, // 110100/01 2, 14, // 110100/10 2, 14, // 110100/11 2, 15, // 110101/00 2, 15, // 110101/01 2, 15, // 110101/10 2, 15, // 110101/11 3, 64, // 11011/000 3, 64, // 11011/001 3, 64, // 11011/010 3, 64, // 11011/011 3, 64, // 11011/100 3, 64, // 11011/101 3, 64, // 11011/110 3, 64, // 11011/111 4, 6, // 1110/0000 4, 6, // 1110/0001 4, 6, // 1110/0010 4, 6, // 1110/0011 4, 6, // 1110/0100 4, 6, // 1110/0101 4, 6, // 1110/0110 4, 6, // 1110/0111 4, 6, // 1110/1000 4, 6, // 1110/1001 4, 6, // 1110/1010 4, 6, // 1110/1011 4, 6, // 1110/1100 4, 6, // 1110/1101 4, 6, // 1110/1110 4, 6, // 1110/1111 4, 7, // 1111/0000 4, 7, // 1111/0001 4, 7, // 1111/0010 4, 7, // 1111/0011 4, 7, // 1111/0100 4, 7, // 1111/0101 4, 7, // 1111/0110 4, 7, // 1111/0111 4, 7, // 1111/1000 4, 7, // 1111/1001 4, 7, // 1111/1010 4, 7, // 1111/1011 4, 7, // 1111/1100 4, 7, // 1111/1101 4, 7, // 1111/1110 4, 7, // 1111/1111 // prefix: 00000000, offset 256 0, -1, // 00000000 0000 0, -2, // 00000000 0001 0, -1, // 00000000 0010 0, -1, // 00000000 0011 0, -1, // 00000000 0100 0, -1, // 00000000 0101 0, -1, // 00000000 0110 0, -1, // 00000000 0111 0, -1, // 00000000 1000 0, -1, // 00000000 1001 0, -1, // 00000000 1010 0, -1, // 00000000 1011 0, -1, // 00000000 1100 0, -1, // 00000000 1101 0, -1, // 00000000 1110 0, -1, // 00000000 1111 // prefix: 00000001, offset 272 1, 1792, // 00000001 000/0 1, 1792, // 00000001 000/1 0, 1984, // 00000001 0010 0, 2048, // 00000001 0011 0, 2112, // 00000001 0100 0, 2176, // 00000001 0101 0, 2240, // 00000001 0110 0, 2304, // 00000001 0111 1, 1856, // 00000001 100/0 1, 1856, // 00000001 100/1 1, 1920, // 00000001 101/0 1, 1920, // 00000001 101/1 0, 2368, // 00000001 1100 0, 2432, // 00000001 1101 0, 2496, // 00000001 1110 0, 2560, // 00000001 1111 // prefix: 01001100, offset 288 0, 1472, // 01001100 0 0, 1536, // 01001100 1 // prefix: 01001101, offset 290 0, 1600, // 01001101 0 0, 1728, // 01001101 1 // prefix: 01100110, offset 292 0, 704, // 01100110 0 0, 768, // 01100110 1 // prefix: 01101001, offset 294 0, 832, // 01101001 0 0, 896, // 01101001 1 // prefix: 01101010, offset 296 0, 960, // 01101010 0 0, 1024, // 01101010 1 // prefix: 01101011, offset 298 0, 1088, // 01101011 0 0, 1152, // 01101011 1 // prefix: 01101100, offset 300 0, 1216, // 01101100 0 0, 1280, // 01101100 1 // prefix: 01101101, offset 302 0, 1344, // 01101101 0 0, 1408 // 01101101 1 }; static ExtractTable blackExtract[] = { -3, 256, // 00000000.... -4, 264, // 00000001.... (1792+) -5, 280, // 00000010.... -5, 312, // 00000011.... 0, 13, // 00000100 -4, 344, // 00000101.... -4, 360, // 00000110.... 0, 14, // 00000111 1, 10, // 0000100/0 1, 10, // 0000100/1 1, 11, // 0000101/0 1, 11, // 0000101/1 -4, 376, // 00001100.... -4, 392, // 00001101.... 1, 12, // 0000111/0 1, 12, // 0000111/1 2, 9, // 000100/00 2, 9, // 000100/01 2, 9, // 000100/10 2, 9, // 000100/11 2, 8, // 000101/00 2, 8, // 000101/01 2, 8, // 000101/10 2, 8, // 000101/11 3, 7, // 00011/000 3, 7, // 00011/001 3, 7, // 00011/010 3, 7, // 00011/011 3, 7, // 00011/100 3, 7, // 00011/101 3, 7, // 00011/110 3, 7, // 00011/111 4, 6, // 0010/0000 4, 6, // 0010/0001 4, 6, // 0010/0010 4, 6, // 0010/0011 4, 6, // 0010/0100 4, 6, // 0010/0101 4, 6, // 0010/0110 4, 6, // 0010/0111 4, 6, // 0010/1000 4, 6, // 0010/1001 4, 6, // 0010/1010 4, 6, // 0010/1011 4, 6, // 0010/1100 4, 6, // 0010/1101 4, 6, // 0010/1110 4, 6, // 0010/1111 4, 5, // 0011/0000 4, 5, // 0011/0001 4, 5, // 0011/0010 4, 5, // 0011/0011 4, 5, // 0011/0100 4, 5, // 0011/0101 4, 5, // 0011/0110 4, 5, // 0011/0111 4, 5, // 0011/1000 4, 5, // 0011/1001 4, 5, // 0011/1010 4, 5, // 0011/1011 4, 5, // 0011/1100 4, 5, // 0011/1101 4, 5, // 0011/1110 4, 5, // 0011/1111 5, 1, // 010/00000 5, 1, // 010/00001 5, 1, // 010/00010 5, 1, // 010/00011 5, 1, // 010/00100 5, 1, // 010/00101 5, 1, // 010/00110 5, 1, // 010/00111 5, 1, // 010/01000 5, 1, // 010/01001 5, 1, // 010/01010 5, 1, // 010/01011 5, 1, // 010/01100 5, 1, // 010/01101 5, 1, // 010/01110 5, 1, // 010/01111 5, 1, // 010/10000 5, 1, // 010/10001 5, 1, // 010/10010 5, 1, // 010/10011 5, 1, // 010/10100 5, 1, // 010/10101 5, 1, // 010/10110 5, 1, // 010/10111 5, 1, // 010/11000 5, 1, // 010/11001 5, 1, // 010/11010 5, 1, // 010/11011 5, 1, // 010/11100 5, 1, // 010/11101 5, 1, // 010/11110 5, 1, // 010/11111 5, 4, // 011/00000 5, 4, // 011/00001 5, 4, // 011/00010 5, 4, // 011/00011 5, 4, // 011/00100 5, 4, // 011/00101 5, 4, // 011/00110 5, 4, // 011/00111 5, 4, // 011/01000 5, 4, // 011/01001 5, 4, // 011/01010 5, 4, // 011/01011 5, 4, // 011/01100 5, 4, // 011/01101 5, 4, // 011/01110 5, 4, // 011/01111 5, 4, // 011/10000 5, 4, // 011/10001 5, 4, // 011/10010 5, 4, // 011/10011 5, 4, // 011/10100 5, 4, // 011/10101 5, 4, // 011/10110 5, 4, // 011/10111 5, 4, // 011/11000 5, 4, // 011/11001 5, 4, // 011/11010 5, 4, // 011/11011 5, 4, // 011/11100 5, 4, // 011/11101 5, 4, // 011/11110 5, 4, // 011/11111 6, 3, // 10/000000 6, 3, // 10/000001 6, 3, // 10/000010 6, 3, // 10/000011 6, 3, // 10/000100 6, 3, // 10/000101 6, 3, // 10/000110 6, 3, // 10/000111 6, 3, // 10/001000 6, 3, // 10/001001 6, 3, // 10/001010 6, 3, // 10/001011 6, 3, // 10/001100 6, 3, // 10/001101 6, 3, // 10/001110 6, 3, // 10/001111 6, 3, // 10/010000 6, 3, // 10/010001 6, 3, // 10/010010 6, 3, // 10/010011 6, 3, // 10/010100 6, 3, // 10/010101 6, 3, // 10/010110 6, 3, // 10/010111 6, 3, // 10/011000 6, 3, // 10/011001 6, 3, // 10/011010 6, 3, // 10/011011 6, 3, // 10/011100 6, 3, // 10/011101 6, 3, // 10/011110 6, 3, // 10/011111 6, 3, // 10/100000 6, 3, // 10/100001 6, 3, // 10/100010 6, 3, // 10/100011 6, 3, // 10/100100 6, 3, // 10/100101 6, 3, // 10/100110 6, 3, // 10/100111 6, 3, // 10/101000 6, 3, // 10/101001 6, 3, // 10/101010 6, 3, // 10/101011 6, 3, // 10/101100 6, 3, // 10/101101 6, 3, // 10/101110 6, 3, // 10/101111 6, 3, // 10/110000 6, 3, // 10/110001 6, 3, // 10/110010 6, 3, // 10/110011 6, 3, // 10/110100 6, 3, // 10/110101 6, 3, // 10/110110 6, 3, // 10/110111 6, 3, // 10/111000 6, 3, // 10/111001 6, 3, // 10/111010 6, 3, // 10/111011 6, 3, // 10/111100 6, 3, // 10/111101 6, 3, // 10/111110 6, 3, // 10/111111 6, 2, // 11/000000 6, 2, // 11/000001 6, 2, // 11/000010 6, 2, // 11/000011 6, 2, // 11/000100 6, 2, // 11/000101 6, 2, // 11/000110 6, 2, // 11/000111 6, 2, // 11/001000 6, 2, // 11/001001 6, 2, // 11/001010 6, 2, // 11/001011 6, 2, // 11/001100 6, 2, // 11/001101 6, 2, // 11/001110 6, 2, // 11/001111 6, 2, // 11/010000 6, 2, // 11/010001 6, 2, // 11/010010 6, 2, // 11/010011 6, 2, // 11/010100 6, 2, // 11/010101 6, 2, // 11/010110 6, 2, // 11/010111 6, 2, // 11/011000 6, 2, // 11/011001 6, 2, // 11/011010 6, 2, // 11/011011 6, 2, // 11/011100 6, 2, // 11/011101 6, 2, // 11/011110 6, 2, // 11/011111 6, 2, // 11/100000 6, 2, // 11/100001 6, 2, // 11/100010 6, 2, // 11/100011 6, 2, // 11/100100 6, 2, // 11/100101 6, 2, // 11/100110 6, 2, // 11/100111 6, 2, // 11/101000 6, 2, // 11/101001 6, 2, // 11/101010 6, 2, // 11/101011 6, 2, // 11/101100 6, 2, // 11/101101 6, 2, // 11/101110 6, 2, // 11/101111 6, 2, // 11/110000 6, 2, // 11/110001 6, 2, // 11/110010 6, 2, // 11/110011 6, 2, // 11/110100 6, 2, // 11/110101 6, 2, // 11/110110 6, 2, // 11/110111 6, 2, // 11/111000 6, 2, // 11/111001 6, 2, // 11/111010 6, 2, // 11/111011 6, 2, // 11/111100 6, 2, // 11/111101 6, 2, // 11/111110 6, 2, // 11/111111 // prefix: 00000000, offset 256 0, -2, // 00000000 000 0, -1, // 00000000 001 0, -1, // 00000000 010 0, -1, // 00000000 011 0, -1, // 00000000 100 0, -1, // 00000000 101 0, -1, // 00000000 110 0, -1, // 00000000 111 // prefix: 00000001, offset 264 1, 1792, // 00000001 000/0 1, 1792, // 00000001 000/1 0, 1984, // 00000001 0010 0, 2048, // 00000001 0011 0, 2112, // 00000001 0100 0, 2176, // 00000001 0101 0, 2240, // 00000001 0110 0, 2304, // 00000001 0111 1, 1856, // 00000001 100/0 1, 1856, // 00000001 100/1 1, 1920, // 00000001 101/0 1, 1920, // 00000001 101/1 0, 2368, // 00000001 1100 0, 2432, // 00000001 1101 0, 2496, // 00000001 1110 0, 2560, // 00000001 1111 // prefix: 00000010, offset 280 3, 18, // 00000010 00/000 3, 18, // 00000010 00/001 3, 18, // 00000010 00/010 3, 18, // 00000010 00/011 3, 18, // 00000010 00/100 3, 18, // 00000010 00/101 3, 18, // 00000010 00/110 3, 18, // 00000010 00/111 1, 52, // 00000010 0100/0 1, 52, // 00000010 0100/1 0, 640, // 00000010 01010 0, 704, // 00000010 01011 0, 768, // 00000010 01100 0, 832, // 00000010 01101 1, 55, // 00000010 0111/0 1, 55, // 00000010 0111/1 1, 56, // 00000010 1000/0 1, 56, // 00000010 1000/1 0, 1280, // 00000010 10010 0, 1344, // 00000010 10011 0, 1408, // 00000010 10100 0, 1472, // 00000010 10101 1, 59, // 00000010 1011/0 1, 59, // 00000010 1011/1 1, 60, // 00000010 1100/0 1, 60, // 00000010 1100/1 0, 1536, // 00000010 11010 0, 1600, // 00000010 11011 2, 24, // 00000010 111/00 2, 24, // 00000010 111/01 2, 24, // 00000010 111/10 2, 24, // 00000010 111/11 // prefix: 00000011, offset 312 2, 25, // 00000011 000/00 2, 25, // 00000011 000/01 2, 25, // 00000011 000/10 2, 25, // 00000011 000/11 0, 1664, // 00000011 00100 0, 1728, // 00000011 00101 1, 320, // 00000011 0011/0 1, 320, // 00000011 0011/1 1, 384, // 00000011 0100/0 1, 384, // 00000011 0100/1 1, 448, // 00000011 0101/0 1, 448, // 00000011 0101/1 0, 512, // 00000011 01100 0, 576, // 00000011 01101 1, 53, // 00000011 0111/0 1, 53, // 00000011 0111/1 1, 54, // 00000011 1000/0 1, 54, // 00000011 1000/1 0, 896, // 00000011 10010 0, 960, // 00000011 10011 0, 1024, // 00000011 10100 0, 1088, // 00000011 10101 0, 1152, // 00000011 10110 0, 1216, // 00000011 10111 3, 64, // 00000011 11/000 3, 64, // 00000011 11/001 3, 64, // 00000011 11/010 3, 64, // 00000011 11/011 3, 64, // 00000011 11/100 3, 64, // 00000011 11/101 3, 64, // 00000011 11/110 3, 64, // 00000011 11/111 // prefix: 00000101, offset 344 1, 23, // 00000101 000/0 1, 23, // 00000101 000/1 0, 50, // 00000101 0010 0, 51, // 00000101 0011 0, 44, // 00000101 0100 0, 45, // 00000101 0101 0, 46, // 00000101 0110 0, 47, // 00000101 0111 0, 57, // 00000101 1000 0, 58, // 00000101 1001 0, 61, // 00000101 1010 0, 256, // 00000101 1011 2, 16, // 00000101 11/00 2, 16, // 00000101 11/01 2, 16, // 00000101 11/10 2, 16, // 00000101 11/11 // prefix: 00000110, offset 360 2, 17, // 00000110 00/00 2, 17, // 00000110 00/01 2, 17, // 00000110 00/10 2, 17, // 00000110 00/11 0, 48, // 00000110 0100 0, 49, // 00000110 0101 0, 62, // 00000110 0110 0, 63, // 00000110 0111 0, 30, // 00000110 1000 0, 31, // 00000110 1001 0, 32, // 00000110 1010 0, 33, // 00000110 1011 0, 40, // 00000110 1100 0, 41, // 00000110 1101 1, 22, // 00000110 111/0 1, 22, // 00000110 111/1 // prefix: 00001100, offset 376 3, 15, // 00001100 0/000 3, 15, // 00001100 0/001 3, 15, // 00001100 0/010 3, 15, // 00001100 0/011 3, 15, // 00001100 0/100 3, 15, // 00001100 0/101 3, 15, // 00001100 0/110 3, 15, // 00001100 0/111 0, 128, // 00001100 1000 0, 192, // 00001100 1001 0, 26, // 00001100 1010 0, 27, // 00001100 1011 0, 28, // 00001100 1100 0, 29, // 00001100 1101 1, 19, // 00001100 111/0 1, 19, // 00001100 111/1 // prefix: 00001101, offset 392 1, 20, // 00001101 000/0 1, 20, // 00001101 000/1 0, 34, // 00001101 0010 0, 35, // 00001101 0011 0, 36, // 00001101 0100 0, 37, // 00001101 0101 0, 38, // 00001101 0110 0, 39, // 00001101 0111 1, 21, // 00001101 100/0 1, 21, // 00001101 100/1 0, 42, // 00001101 1010 0, 43, // 00001101 1011 2, 0, // 00001101 11/00 2, 0, // 00001101 11/01 2, 0, // 00001101 11/10 2, 0 // 00001101 11/11 }; \ No newline at end of file diff --git a/Source/C/UpdateRegion.c b/Source/C/UpdateRegion.c new file mode 100644 index 0000000..464b2d7 --- /dev/null +++ b/Source/C/UpdateRegion.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ // short *UpdateRegion(short *rgnData, RgnBufferPtr rgnBuffer, Rect *boxRect) long *bufData = rgnBuffer->buffer, *ptr, tmp; long x, lastY; lastY = rgnData[-1]; // get last Y coordinate while ((x = *rgnData++) != 0x7fff) { x -= boxRect->left; while (*bufData < x) bufData++; ptr = bufData; if (x == *bufData) while ((*ptr = *(ptr + 1)) != 0x7fff) ptr++; else { while (x != 0x7fff) { tmp = *ptr; *ptr++ = x; x = tmp; } *ptr++ = x; bufData++; } } rgnBuffer->yCount = *rgnData++ - lastY; return rgnData; /* parameter passing: r3 = rgnData r4 = rgnBuffer r5 = boxRect 00000000: BF61FFEC stmw r27,-20(SP) long *bufData = rgnBuffer->buffer, *ptr, tmp; long x, lastY; lastY = rgnData[-1]; // get last Y coordinate 00000004: AB63FFFE lha lastY,-2(rgnData) 00000008: 3BA40008 addi bufData,rgnBuffer,8 while ((x = *rgnData++) != 0x7fff) { x -= boxRect->left; 0000000C: 42800078 bc ALWAYS,cr0_LT,$00000084 00000010: A8C50002 lha r6,2(boxRect) 00000014: 7FE6F850 sub x,x,r6 while (*bufData < x) bufData++; 00000018: 42800008 bc ALWAYS,cr0_LT,$00000020 0000001C: 3BBD0004 addi bufData,bufData,4 00000020: 80FD0000 lwz r7,0(bufData) 00000024: 7C07F800 cmpw r7,x 00000028: 4180FFF4 blt $0000001C ptr = bufData; 0000002C: 811D0000 lwz r8,0(bufData) 00000030: 7FBEEB78 mr ptr,bufData if (x == *bufData) 00000034: 7C1F4000 cmpw x,r8 00000038: 40820034 bne $0000006C while ((*ptr = *(ptr + 1)) != 0x7fff) ptr++; 0000003C: 42800008 bc ALWAYS,cr0_LT,$00000044 00000040: 3BDE0004 addi ptr,ptr,4 00000044: 813E0004 lwz r9,4(ptr) 00000048: 2C097FFF cmpwi r9,32767 0000004C: 913E0000 stw r9,0(ptr) 00000050: 4082FFF0 bne $00000040 00000054: 42800030 bc ALWAYS,cr0_LT,$00000084 else { while (x != 0x7fff) { tmp = *ptr; *ptr++ = x; x = tmp; } 00000058: 839E0000 lwz tmp,0(ptr) 0000005C: 7FCAF378 mr r10,ptr 00000060: 93EA0000 stw x,0(r10) 00000064: 3BDE0004 addi ptr,ptr,4 00000068: 7F9FE378 mr x,tmp 0000006C: 2C1F7FFF cmpwi x,32767 00000070: 4082FFE8 bne $00000058 *ptr++ = x; bufData++; 00000074: 7FCBF378 mr r11,ptr 00000078: 3BDE0004 addi ptr,ptr,4 0000007C: 93EB0000 stw x,0(r11) 00000080: 3BBD0004 addi bufData,bufData,4 } 00000084: 7C6C1B78 mr r12,rgnData 00000088: ABEC0000 lha x,0(r12) 0000008C: 38630002 addi rgnData,rgnData,2 00000090: 2C1F7FFF cmpwi x,32767 00000094: 4082FF7C bne $00000010 } rgnBuffer->yCount = *rgnData++ - lastY; return rgnData; 00000098: 7C661B78 mr r6,rgnData 0000009C: A8C60000 lha r6,0(r6) 000000A0: 38630002 addi rgnData,rgnData,2 000000A4: 7CDB3050 sub r6,r6,lastY 000000A8: 90C40000 stw r6,0(rgnBuffer) 000000AC: BB61FFEC lmw r27,-20(SP) 000000B0: 4E800020 blr */ \ No newline at end of file diff --git a/Source/C/ViewMenu.c b/Source/C/ViewMenu.c new file mode 100644 index 0000000..20dd435 --- /dev/null +++ b/Source/C/ViewMenu.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * HandleViewChoice(theItem) * * Purpose: Accepts menu events from the View menu * Inputs: theItem = the menu item number * Returns: nothing * */ void HandleViewChoice(short theItem) { ImageHandle theImage = FrontImage(); Rect newRect, theRect, tmpRect; MonitorHandle mostMonitor; if (!theImage) return; newRect = (*theImage)->wrect; GlobalRect(&newRect, (*theImage)->window); mostMonitor = GetMostDevice(&newRect); OffsetRect(&newRect, -newRect.left, -newRect.top); switch (theItem) { case viewFullScreenItem: (*theImage)->dmon = mostMonitor; SendSetFullScreen((*theImage)->window, !Full(theImage)); break; case viewResizeItem: (*theImage)->dmon = mostMonitor; newRect = (*theImage)->crect; ScaleRect(&newRect, (*theImage)->dmon, Full(theImage), gThePrefs.expandSmall); SendSetDrawBounds((*theImage)->window, &newRect); break; case viewNormalItem: GetActiveRect((*theImage)->dmon, &newRect); if (!Full(theImage)) newRect.top += gTitleBarHeight; if ((Width(&(*theImage)->crect) <= Width(&newRect)) && (Height(&(*theImage)->crect) <= Height(&newRect))) { newRect = (*theImage)->crect; SendSetDrawBounds((*theImage)->window, &newRect); } else HandleViewChoice(viewMaxItem); break; case viewHalfItem: newRect.right >>= 1; newRect.bottom >>= 1; SendSetDrawBounds((*theImage)->window, &newRect); break; case viewDoubleItem: newRect.right <<= 1; newRect.bottom <<= 1; SendSetDrawBounds((*theImage)->window, &newRect); break; case viewMaxItem: newRect = (*theImage)->crect; OffsetRect(&newRect, -newRect.left, -newRect.top); GetActiveRect(mostMonitor, &theRect); if (!Full(theImage)) theRect.top += gTitleBarHeight; newRect.right = (long)newRect.right * (long)Height(&theRect) / (long)newRect.bottom; newRect.bottom = Height(&theRect); if (Width(&newRect) > Width(&theRect)) { newRect.bottom = (long)newRect.bottom * (long)Width(&theRect) / (long)newRect.right; newRect.right = Width(&theRect); } SendSetDrawBounds((*theImage)->window, &newRect); break; case viewShrinkItem: newRect.right -= newRect.right / 10; newRect.bottom -= newRect.bottom / 10; SendSetDrawBounds((*theImage)->window, &newRect); break; case viewExpandItem: newRect.right += newRect.right / 10; newRect.bottom += newRect.bottom / 10; SendSetDrawBounds((*theImage)->window, &newRect); break; } } /* * ForceScreenSize(srcRect) * * Purpose: Tries to force srcRect to be exactly screen-sized * Inputs: srcRect = the rectangle to fit * Returns: nothing * */ void ForceScreenSize(ImageHandle theImage, Rect *srcRect) { Rect srect, crect = (*theImage)->crect; GetActiveRect((*theImage)->dmon, &srect); if (!Full(theImage)) srect.top += gTitleBarHeight; while ((Width(srcRect) < Width(&srect)) && (Width(srcRect) <= Width(&crect))) { if ((crect.right - srcRect->right) > (crect.left - srcRect->left)) srcRect->right++; else srcRect->left--; } while ((Width(srcRect) > Width(&srect)) || (Width(srcRect) > Width(&crect))) { if ((crect.right - srcRect->right) > (crect.left - srcRect->left)) srcRect->right--; else srcRect->left++; } while ((Height(srcRect) < Height(&srect)) && (Height(srcRect) <= Height(&crect))) { if ((crect.bottom - srcRect->bottom) > (crect.top - srcRect->top)) srcRect->bottom++; else srcRect->top--; } while ((Height(srcRect) > Height(&srect)) || (Height(srcRect) > Height(&crect))) { if ((crect.bottom - srcRect->bottom) > (crect.top - srcRect->top)) srcRect->bottom--; else srcRect->top++; } if (srcRect->left < crect.left) srcRect->left = crect.left; if (srcRect->right > crect.right) srcRect->right = crect.right; if (srcRect->top < crect.top) srcRect->top = crect.top; if (srcRect->bottom > crect.bottom) srcRect->bottom = crect.bottom; } \ No newline at end of file diff --git a/Source/C/WindowMenu.c b/Source/C/WindowMenu.c new file mode 100644 index 0000000..8db9b0c --- /dev/null +++ b/Source/C/WindowMenu.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * HandleWindowChoice(theItem) * * Purpose: Accepts menu events from the Window menu * Inputs: theItem = the menu item number * Returns: nothing * */ void HandleWindowChoice(short theItem) { ImageHandle theImage; switch (theItem) { case windowStatItem: if (GetStatWindow()) SendCloseWindow(GetStatWindow()); else SendCreateWindow(kStatWindowID); break; case windowCommentsItem: if (GetCommentsWindow()) gCommentsOpen = false, SendCloseWindow(GetCommentsWindow()); else gCommentsOpen = true, SendCreateWindow(kCommentsWindowID); break; case windowColorsItem: if (GetColorsWindow()) SendCloseWindow(GetColorsWindow()); else SendCreateWindow(kColorsWindowID); break; case windowPreviousItem: theImage = FrontImage(); if (theImage) theImage = PreviousImage(theImage); if (!theImage) theImage = LastImage(); SendMoveToFront((*theImage)->window); break; case windowNextItem: theImage = FrontImage(); if (theImage) theImage = (*theImage)->next; if (!theImage) theImage = gImageRoot; SendMoveToFront((*theImage)->window); break; default: SendMoveToFront(IndexedDocument(theItem - windowFirstItem + 1)); break; } } \ No newline at end of file diff --git a/Source/C/WindowUtils.c b/Source/C/WindowUtils.c new file mode 100644 index 0000000..9855c72 --- /dev/null +++ b/Source/C/WindowUtils.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif void SaveWindowPosition(WindowPtr theWindow, Rect *position) { *position = theWindow->portRect; GlobalRect(position, theWindow); if (!gDone) SaveGeneralPrefs(); } void PlaceWindow(WindowPtr theWindow, Rect *theRect, Point defaultLoc) { if (GetWVariant(theWindow) == dBoxProc || theRect->top == theRect->bottom || DoSetWindowBounds(theWindow, theRect) != noErr) { FWMoveWindow(theWindow, defaultLoc.h, defaultLoc.v, true); } } /* * ChangeActive(theWindow) * * Purpose: Changes the active window, flipping the menu bar if necessary and * updating the gActive* variables * Inputs: theWindow = the new active window * Returns: nothing * */ void ChangeActive(WindowPtr theWindow) { static WindowPtr gLastWindow = nil; ImageHandle oldImage = FrontImage(), newImage = nil; WindowPtr oldWindow = FWFrontWindow(); Point thePoint = { 0, 0 }; MySetPort(nil); if (theWindow) { newImage = FindImage(theWindow); if (gSlideShow != kPaused) { if (theWindow == GetSlideBackWindow()) { if ((*gMainMonitor)->full) RehideMenuBar(); else FullScreen(gMainMonitor); } else if (WindowKind(theWindow) != floatingWindowKind) { if (!newImage || !Full(newImage)) { if (newImage && !AnotherFull(newImage)) NormalScreen((*newImage)->dmon); else UnhideMenuBar(); } else { if ((*(*newImage)->dmon)->full) RehideMenuBar(); else FullScreen((*newImage)->dmon); } } } if (!WindowVisible(theWindow)) FWShowWindow(theWindow); FWSelectWindow(theWindow); MySetPort((CGrafPtr)theWindow); if (theWindow) { if (theWindow == GetColorsWindow()) DrawColorsWindow(); else if (theWindow == GetStatWindow()) DrawStatWindow(); } if (newImage && !EmptyRgn((*newImage)->update)) InvalRgn((*newImage)->update); if (newImage) ActivateAnts((*newImage)->ants); } SetStatistics(); if (theWindow != gLastWindow && (!theWindow || WindowKind(theWindow) != floatingWindowKind)) { gLastWindow = theWindow; if ((!gSlideShow && gThePrefs.autoComments) || (gSlideShow && (*gSlideOptions)->autoComments)) { newImage = FrontImage(); if (!newImage || !(*newImage)->comments) { if (GetCommentsWindow()) if ((!gSlideShow && !gCommentsOpen) || gSlideShow) CloseComments(); } else if (!CommentsClosed(newImage) && !GetCommentsWindow() && OpenComments() == noErr) { FWSelectWindow(GetCommentsWindow()); FWShowWindow(GetCommentsWindow()); } } if (GetSlideControlsWindow()) DrawSlideControlsWindow(); if (GetSlideOptionsWindow()) UpdateSlideOptionsButtons(); } AdjustMenus(); } /* * DoCloneWindow(theWindow, behindWindow, newWindow) * * Purpose: Makes a clone of the given window * Inputs: theWindow = the window to clone * behindWindow = the window behind which to put the newcomer * newWindow = a pointer to a WindowPtr to receive the new window * Returns: an OSErr describing the result * */ OSErr DoCloneWindow(WindowPtr theWindow, WindowPtr behindWindow, WindowPtr *newWindow) { ImageHandle newImage, theImage = FindImage(theWindow); DescType thePalette; short palette; OSErr theErr; if (!theImage) return errAENotModifiable; if (newImage = CopyImage(theImage)) { palette = (*newImage)->npalette; theErr = MakeNewWindow(newImage, true, gThePrefs.expandSmall); if (theErr == noErr) { switch ((*theImage)->npalette) { case plSys: thePalette = kAEPSystem; break; case plGrey: thePalette = kAEPGrayscale; break; case plImage: thePalette = kAEPImage; break; case plQuant: thePalette = kAEPQuantized; break; } DoSetPalette((*newImage)->window, thePalette); AddWindowItem(newImage); if (behindWindow) SendBehind((*newImage)->window, behindWindow); *newWindow = (*newImage)->window; } } else theErr = memFullErr; return theErr; } /* * DoCloseWindow(theWindow, restore) * * Purpose: Handles the closing of the given window, disposing of the associated * image, if necessary * Inputs: theWindow = the window to close * restore = flag: true to restore colors when closing last image * Returns: nothing * */ OSErr DoCloseWindow(WindowPtr theWindow, Boolean restore) { WindowPtr statWindow = GetStatWindow(), commentsWindow = GetCommentsWindow(), colorsWindow = GetColorsWindow(), slideBackWindow = GetSlideBackWindow(), slideControlsWindow = GetSlideControlsWindow(); ImageHandle theImage = FindImage(theWindow); long dialogID = GetWRefCon(theWindow); Boolean reset = false; ushort i = 0; MySetPort(nil); if (WindowKind(theWindow) == dialogKind) DispatchDialogEvent(theWindow, kDialogClose); else if (dialogID == kHelpWindowID) CloseHelp(); else if (theWindow == statWindow) CloseStats(); else if (theWindow == commentsWindow) { ImageHandle frontImage = FrontImage(); gCommentsOpen = false, CloseComments(); if ((!gSlideShow && gThePrefs.autoComments) || (gSlideShow && (*gSlideOptions)->autoComments)) if (frontImage) (*frontImage)->flags |= ifCommentsClosed; } else if (theWindow == colorsWindow) CloseColors(); else if (theWindow == slideControlsWindow) CloseSlideControls(); else if (theWindow == slideBackWindow) CloseSlideBackWindow(); else if (theImage) { Boolean normal = (Full(theImage) && !AnotherFull(theImage)); MonitorHandle imageMonitor = (*theImage)->dmon; if (normal) NormalScreen(imageMonitor); DeleteWindowItem(theImage); DisposeImage(theImage); if (!gImageRoot && theImage && (restore || gDone)) ResetColors(); } ChangeActive(FWFrontWindow()); return noErr; } /* * DoCreateWindow(theType, behindWindow, theWindow) * * Purpose: Handles the creation of static windows and positions them correctly * Inputs: theType = the type of window to create * behindWindow = the window's location * theWindow = pointer to receive the new WindowPtr * Returns: nothing * */ OSErr DoCreateWindow(DescType theType, WindowPtr behindWindow, WindowPtr *theWindow) { ImageHandle theImage; OSErr theErr = noErr; switch (theType) { case kAEWTPreferences: OpenPrefs(); if (*theWindow = GetPrefsWindow()) ChangeActive(*theWindow); else theErr = memFullErr; break; case kAEWTSlideShow: OpenSlideOptions(); if (*theWindow = GetSlideOptionsWindow()) ChangeActive(*theWindow); else theErr = memFullErr; break; case kAEWTAboutHelp: OpenAboutHelp(); if (*theWindow = GetAboutHelpWindow()) ChangeActive(*theWindow); else theErr = memFullErr; break; case kAEWTHelp: if (!gHelpFound) theErr = errNoHelpFound; else { OpenHelp(); if (*theWindow = GetHelpWindow()) { DoMoveWindow(*theWindow, behindWindow); FWShowWindow(*theWindow); } else theErr = memFullErr; } break; case kAEWTStatistics: OpenStats(); if (*theWindow = GetStatWindow()) { DoMoveWindow(*theWindow, behindWindow); FWShowWindow(*theWindow); } else theErr = memFullErr; break; case kAEWTComments: OpenComments(); if (*theWindow = GetCommentsWindow()) { DoMoveWindow(*theWindow, behindWindow); FWShowWindow(*theWindow); } else theErr = memFullErr; break; case kAEWTColors: OpenColors(); if (*theWindow = GetColorsWindow()) { DoMoveWindow(*theWindow, behindWindow); FWShowWindow(*theWindow); } else theErr = memFullErr; break; case kAEWTSlideControls: OpenSlideControls(); if (*theWindow = GetColorsWindow()) { DoMoveWindow(*theWindow, behindWindow); FWShowWindow(*theWindow); } else theErr = memFullErr; case kAEWTAbout: OpenAbout(); for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) if (IsAboutBox(theImage)) break; if (theImage && (*theWindow = (*theImage)->window)) { DoMoveWindow(*theWindow, behindWindow); FWShowWindow(*theWindow); } else theErr = memFullErr; break; } return theErr; } /* * DoMoveWindow(theWindow, behindWindow) * * Purpose: Handles the proper moving of windows in the floating window environment * Inputs: theWindow = the window to move * behindWindow = the window's location * Returns: nothing * */ OSErr DoMoveWindow(WindowPtr theWindow, WindowPtr behindWindow) { if (theWindow == behindWindow) return noErr; if (WindowKind(theWindow) == floatingWindowKind) { if (!behindWindow) ChangeActive(theWindow); else { if (WindowKind(behindWindow) != floatingWindowKind) behindWindow = FWBottomFloatingWindow(); SendBehind(theWindow, behindWindow); } } else { if (!behindWindow || WindowKind(behindWindow) == floatingWindowKind) ChangeActive(theWindow); else SendBehind(theWindow, behindWindow); } return noErr; } /* * IsZoomed(theWindow) * * Purpose: Determines the zoomed state of the given window * Inputs: theWindow = the window to examine * Returns: a boolean: true if the window is zoomed; false otherwise * */ Boolean IsZoomed(WindowPtr theWindow) { ImageHandle theImage = FindImage(theWindow); if (theImage) return !EqualSizeRect(&(*theImage)->wrect, &(*theImage)->crect); else if (theWindow == GetStatWindow()) return gThePrefs.statsZoomed; else if (theWindow == GetHelpWindow()) { Rect defaultRect = { 0, 0, 300, 480 }; return !EqualSizeRect(&theWindow->portRect, &defaultRect); } else return false; } /* * DoZoomWindow(theWindow, zoomed) * * Purpose: Zooms the given window * Inputs: theWindow = the window to clone * zoomed = flag: true to zoom the window, false to unzoom * Returns: an OSErr describing the result * */ OSErr DoZoomWindow(WindowPtr theWindow, Boolean zoomed) { ImageHandle theImage = FindImage(theWindow); Rect newRect, oldRect, monRect; if (theImage) { oldRect = (*theImage)->wrect; newRect = (*theImage)->crect; GetActiveRect((*theImage)->dmon, &monRect); if (!Full(theImage)) monRect.top += gTitleBarHeight; if (zoomed || (Width(&newRect) > Width(&monRect)) || (Height(&newRect) > Height(&monRect))) { OffsetRect(&newRect, -newRect.left, -newRect.top); newRect.right = (long)newRect.right * (long)Height(&monRect) / (long)newRect.bottom; newRect.bottom = Height(&monRect); if (Width(&newRect) > Width(&monRect)) { newRect.bottom = (long)newRect.bottom * (long)Width(&monRect) / (long)newRect.right; newRect.right = Width(&monRect); } } (*theImage)->wrect = newRect; ResizeWindow(theImage); if (AntsHaveSelection((*theImage)->ants)) { Rect selRect; GetAntsSelection((*theImage)->ants, &selRect); MapRect(&selRect, &oldRect, &(*theImage)->wrect); SetAntsSelection((*theImage)->ants, &selRect); } } else if ((theWindow == GetStatWindow()) && (!gThePrefs.statsZoomed != !zoomed)) ZoomStats(); else if (theWindow == GetHelpWindow()) { Rect defaultRect = { 0, 0, 300, 480 }; if (zoomed) { defaultRect = theWindow->portRect; GlobalRect(&defaultRect, theWindow); GetActiveRect(GetMostDevice(&defaultRect), &defaultRect); InsetRect(&defaultRect, kWindowBorderWidth, kWindowBorderHeight); defaultRect.top += gTitleBarHeight; } else { GlobalRect(&defaultRect, theWindow); NudgeWindowRect(&defaultRect, GetMostDevice(&defaultRect)); } FWMoveWindow(theWindow, defaultRect.left, defaultRect.top, false); ResizeHelp(&defaultRect); } return noErr; } /* * MakeNewWindow(theImage, first, autoExpand) * * Purpose: Creates a new window for the given image, closing the old one if it exists * Inputs: theImage = a pointer to the image record * first = flag: true if this is the first image in a series, false * if this is just a follower * autoExpand = flag: true to expand small images to largest size * Returns: an OSErr describing the problem (hopefully noErr) * */ OSErr MakeNewWindow(ImageHandle theImage, Boolean first, Boolean autoExpand) { static WindowPtr gLastWindow = nil; short resID = Full(theImage) ? rFullImageWindow : ((IsAboutBox(theImage)) ? rAboutImageWindow : rImageWindow); Rect winRect, oldRect = { 0, 0, 0, 0 }; WindowPtr behindWindow; WCTabHandle winColors; Str255 theTitle; if (AntsHaveSelection((*theImage)->ants)) HideAnts((*theImage)->ants); (*theImage)->wrect = (*theImage)->crect; ScaleRect(&(*theImage)->wrect, (*theImage)->dmon, Full(theImage), autoExpand); if (Full(theImage)) { winRect = (*(*theImage)->dmon)->rect; OffsetRect(&(*theImage)->wrect, (Width(&winRect) - Width(&(*theImage)->wrect)) >> 1, (Height(&winRect) - Height(&(*theImage)->wrect)) >> 1); } else { winRect = (*theImage)->wrect; PositionWindow(&winRect, (*theImage)->dmon); } if (gSlideShow) behindWindow = FWFrontWindow(); else behindWindow = (first) ? (WindowPtr)-1 : gLastWindow; if ((*theImage)->window) { oldRect = (*theImage)->window->portRect; GlobalRect(&oldRect, (*theImage)->window); FWCloseWindow((*theImage)->window); } else { (*theImage)->window = AllocateWindow(); if (!(*theImage)->window) return memFullErr; } MakeTitle(theImage, theTitle); MySetPort(nil); if (!FWGetNewCWindow(resID, (Ptr)(*theImage)->window, behindWindow)) return memFullErr; SetWindowKind((*theImage)->window, userKind); if (NeedsWhiteBG(theImage) && !Full(theImage) && (winColors = (WCTabHandle)GetResource('wctb', 0))) SetWinColor((*theImage)->window, winColors); SizeWindow((*theImage)->window, Width(&winRect), Height(&winRect), false); FWMoveWindow((*theImage)->window, winRect.left, winRect.top, false); SetWTitle((*theImage)->window, theTitle); SetAntsPort((*theImage)->ants, (*theImage)->window); SetAntsLimitRect((*theImage)->ants, &(*theImage)->wrect); gLastWindow = (*theImage)->window; if (AntsHaveSelection((*theImage)->ants)) { Rect selRect; GetAntsSelection((*theImage)->ants, &selRect); MapRect(&selRect, &oldRect, &(*theImage)->wrect); SetAntsSelection((*theImage)->ants, &selRect); } if (!GWOrigSize(theImage) && (!EqualSizeRect(&(*theImage)->wrect, &oldRect) || Dithered(theImage))) KillGWorld(theImage); return noErr; } /* * ScaleRect(theRect, theMonitor, full) * * Purpose: Scales the given rectangle to fit on the specified monitor * Inputs: theRect = pointer to the rectangle to be fit * theMonitor = pointer to the monitor to put the rect on * full = flag: true if it will be displayed full screen * Returns: nothing * */ void ScaleRect(Rect *theRect, MonitorHandle theMonitor, Boolean full, Boolean autoExpand) { long theWidth, theHeight; theWidth = Width(&(*theMonitor)->rect); theHeight = Height(&(*theMonitor)->rect); if (!full) { theHeight -= gTitleBarHeight; if (theMonitor == gMainMonitor) theHeight -= gMenuHeight; } OffsetRect(theRect, -theRect->left, -theRect->top); if ((theRect->right > theWidth) || autoExpand) { theRect->bottom = (long)theRect->bottom * theWidth / (long)theRect->right; theRect->right = theWidth; } if (theRect->bottom > theHeight) { theRect->right = (long)theRect->right * theHeight / (long)theRect->bottom; theRect->bottom = theHeight; } } /* * MakeTitle(theImage, theTitle) * * Purpose: Creates a window title for the given image * Inputs: theImage = a pointer to the image * theTitle = an Str255 to store the title in * Returns: nothing * */ void MakeTitle(ImageHandle theImage, StringPtr theTitle) { long scaleX, scaleY; BlockMove((*theImage)->file.name, theTitle, 64); if ((*theImage)->num) { AddChar(theTitle, ' '); AddNumber(theTitle, (*theImage)->num); } if (!EqualSizeRect(&(*theImage)->wrect, &(*theImage)->crect)) { scaleX = 200L * (long)Width(&(*theImage)->wrect) / Width(&(*theImage)->crect); scaleX = (scaleX + 1) >> 1; scaleY = 200L * (long)Height(&(*theImage)->wrect) / Height(&(*theImage)->crect); scaleY = (scaleY + 1) >> 1; AddChar(theTitle, ' '); AddChar(theTitle, '('); if (abs(scaleX - scaleY) <= 1) { AddNumber(theTitle, (scaleX + scaleY) / 2); } else { AddNumber(theTitle, scaleX); AddChar(theTitle, '%'); AddChar(theTitle, '/'); AddNumber(theTitle, scaleY); } AddChar(theTitle, '%'); AddChar(theTitle, ')'); } } /* * PositionWindow(theRect, theMonitor) * * Purpose: Attempts to find the next free slot for a given image rectangle; it first * tries the given upper-left, then scans downward, and finally to the * right for an ideal spot; if nothing else is found, the original * upper-left is returned * Inputs: theRect = a pointer to the proposed image rectangle in global coordinates * theMonitor = a pointer to the monitor rectangle * Returns: nothing * */ void PositionWindow(Rect *theRect, MonitorHandle theMonitor) { short rightSpace, bottomSpace, shift; Rect monRect, startRect; monRect = (*theMonitor)->rect; monRect.top += gTitleBarHeight; if (theMonitor == gMainMonitor) monRect.top += gMenuHeight; OffsetRect(theRect, monRect.left - theRect->left, monRect.top - theRect->top); rightSpace = monRect.right - theRect->right; bottomSpace = monRect.bottom - theRect->bottom; if (rightSpace < (2 * kWindowBorderWidth)) OffsetRect(theRect, rightSpace >> 1, 0); else OffsetRect(theRect, kWindowBorderWidth, 0); if (bottomSpace < (2 * kWindowBorderHeight)) OffsetRect(theRect, 0, bottomSpace >> 1); else OffsetRect(theRect, 0, kWindowBorderHeight); rightSpace = monRect.right - theRect->right; bottomSpace = monRect.bottom - theRect->bottom; startRect = *theRect; for (shift = 0; shift < bottomSpace; shift += kWindowStepDown) { *theRect = startRect; OffsetRect(theRect, 0, shift); while ((theRect->right <= monRect.right) && (theRect->bottom <= monRect.bottom)) { if (!SlotTaken(theRect)) return; OffsetRect(theRect, kWindowStepRight, kWindowStepDown); } } for (shift = 0; shift < rightSpace; shift += kWindowStepRight) { *theRect = startRect; OffsetRect(theRect, shift, 0); while ((theRect->right <= monRect.right) && (theRect->bottom <= monRect.bottom)) { if (!SlotTaken(theRect)) return; OffsetRect(theRect, kWindowStepRight, kWindowStepDown); } } *theRect = startRect; return; } /* * SlotTaken(theRect) * * Purpose: Determines if the proposed rectangle is already taken by another * window, within half of the step distance * Inputs: theRect = the proposed rectangle * Returns: true if the given slot is free; false otherwise * */ Boolean SlotTaken(Rect *theRect) { ImageHandle theImage; WindowPtr theWindow; register short temp; for (theImage = gImageRoot; theImage; theImage = (*theImage)->next) { theWindow = (*theImage)->window; if (theWindow && GetContRgn(theWindow) && WindowVisible(theWindow)) { temp = theRect->left - (*GetContRgn(theWindow))->rgnBBox.left; if (temp < 0) temp = -temp; if (temp >= (kWindowStepRight / 2)) continue; temp = theRect->top - (*GetContRgn(theWindow))->rgnBBox.top; if (temp < 0) temp = -temp; if (temp >= (kWindowStepDown / 2)) continue; return true; } } return false; } /* * ResizeWindow(theImage) * * Purpose: Resizes and displays the window for the given image * Inputs: theImage = a pointer to the image record * Returns: true if everything went okay; false otherwise * */ Boolean ResizeWindow(ImageHandle theImage) { Rect windowRect, oldRect, oldLocalRect; Str255 theTitle; short space; if (!(*theImage)->window) return false; if (AntsHaveSelection((*theImage)->ants)) HideAnts((*theImage)->ants); oldLocalRect = oldRect = (*theImage)->window->portRect; GlobalRect(&oldRect, (*theImage)->window); windowRect = (*theImage)->wrect; OffsetRect(&(*theImage)->wrect, -windowRect.left, -windowRect.top); OffsetRect(&windowRect, oldRect.left - windowRect.left, oldRect.top - windowRect.top); if (Full(theImage)) { space = Width(&(*(*theImage)->dmon)->rect) - Width(&(*theImage)->wrect); OffsetRect(&(*theImage)->wrect, space >> 1, 0); space = Height(&(*(*theImage)->dmon)->rect) - Height(&(*theImage)->wrect); OffsetRect(&(*theImage)->wrect, 0, space >> 1); } else { if (NudgeWindowRect(&windowRect, (*theImage)->dmon)) FWMoveWindow((*theImage)->window, windowRect.left, windowRect.top, false); (*theImage)->wrect = windowRect; OffsetRect(&(*theImage)->wrect, -(*theImage)->wrect.left, -(*theImage)->wrect.top); SizeWindow((*theImage)->window, Width(&windowRect), Height(&windowRect), false); } //if (EqualRect(&(*theImage)->wrect, &oldLocalRect)) return true; PushPort(); MySetPort((CGrafPtr)(*theImage)->window); InvalRect(&(*theImage)->window->portRect); PopPort(); if (!GWOrigSize(theImage) && (!EqualRect(&(*theImage)->wrect, &oldLocalRect) || Dithered(theImage))) KillGWorld(theImage); MakeTitle(theImage, theTitle); SetWTitle((*theImage)->window, theTitle); SetAntsLimitRect((*theImage)->ants, &(*theImage)->wrect); if (AntsHaveSelection((*theImage)->ants)) { Rect selRect; GetAntsSelection((*theImage)->ants, &selRect); MapRect(&selRect, &oldLocalRect, &(*theImage)->wrect); SetAntsSelection((*theImage)->ants, &selRect); } return true; } /* * NudgeWindowRect(windowRect, theMonitor) * * Purpose: Nudges the given rectangle to fit on the monitor * Inputs: windowRect = pointer to the rectangle to nudge * theMonitor = handle to the monitor the rect is on * Returns: true if it needed to be moved; false otherwise * */ Boolean NudgeWindowRect(Rect *windowRect, MonitorHandle theMonitor) { Boolean nudged = false; Rect screenRect; short space; GetActiveRect(theMonitor, &screenRect); screenRect.top += gTitleBarHeight; if (screenRect.right <= windowRect->right) { OffsetRect(windowRect, screenRect.right - windowRect->right, 0); space = windowRect->left - screenRect.left; if (space > (2 * kWindowBorderWidth)) OffsetRect(windowRect, -kWindowBorderWidth, 0); else OffsetRect(windowRect, -(space >> 1), 0); nudged = true; } if (screenRect.left > windowRect->left) { OffsetRect(windowRect, screenRect.left - windowRect->left, 0); space = screenRect.right - windowRect->right; if (space > (2 * kWindowBorderWidth)) OffsetRect(windowRect, kWindowBorderWidth, 0); else OffsetRect(windowRect, (space >> 1), 0); nudged = true; } if (screenRect.bottom <= windowRect->bottom) { OffsetRect(windowRect, 0, screenRect.bottom - windowRect->bottom); space = windowRect->top - screenRect.top; if (space > (2 * kWindowBorderHeight)) OffsetRect(windowRect, 0, -kWindowBorderHeight); else OffsetRect(windowRect, -(space >> 1), 0); nudged = true; } if (screenRect.top > windowRect->top) { OffsetRect(windowRect, 0, screenRect.top - windowRect->top); space = screenRect.bottom - windowRect->bottom; if (space > (2 * kWindowBorderHeight)) OffsetRect(windowRect, 0, kWindowBorderHeight); else OffsetRect(windowRect, (space >> 1), 0); nudged = true; } return nudged; } \ No newline at end of file diff --git a/Source/C/cApplication.c b/Source/C/cApplication.c new file mode 100644 index 0000000..f2e50f5 --- /dev/null +++ b/Source/C/cApplication.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * AppPropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a file property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cFile) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr AppPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, container, containerClass, theRefCon) #endif ObjectTokenHandle theList; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-modifiable properties case pBestType: case pClass: case pClipboard: case pDefaultType: case pIsFrontProcess: case pName: case pUserSelection: case pVersion: break; default: return errAEEventNotHandled; } if (!(theList = MakeSingleObjectToken(nil))) return memFullErr; (*theList)->property = propertyType; (*theList)->objclass = typeNull; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetApplicationData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the application * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetApplicationData(DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; theData->descriptorType = typeNull; theData->dataHandle = nil; return noErr; } /* * GetAppPropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the application's properties * Inputs: theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetAppPropertyData(DescType theProperty, DescType typeWanted, AEDesc *theData) { ProcessSerialNumber thePSN, selfPSN = { 0, kCurrentProcess }; WindowPtr theWindow = FWFrontWindow(); Boolean theBoolean; DescType theType; AEDesc bestData; OSErr theErr; long theLong; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pClass: theType = cApplication; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pClipboard: theErr = AECreateList(nil, 0, false, &bestData); break; case pIsFrontProcess: GetFrontProcess(&thePSN); SameProcess(&selfPSN, &thePSN, &theBoolean); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(DescType), &bestData); break; case pName: theErr = AEMakeIntlDesc(gString[strJPEGView], &bestData); break; case pUserSelection: if (theWindow) theErr = MakeSelectionObject(theWindow, &bestData); else theErr = errAENoSuchObject; break; case pVersion: theLong = kVersion; theErr = AECreateDesc(typeLongInteger, (void *)&theLong, sizeof(long), &bestData); break; default: theErr = errAEReadDenied; break; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetAppPropertyData(theProperty, theData) * * Purpose: Sets the data for the application's properties * Inputs: theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetAppPropertyData(DescType theProperty, AEDesc *theData) { #if applec #pragma unused(theData) #endif OSErr theErr; switch (theProperty) { default: theErr = errAEWriteDenied; break; } return theErr; } /* * MakeAppPropertyObject(theProperty, theObject) * * Purpose: Creates an object descriptor for the given application property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeAppPropertyObject(DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theContainer.descriptorType = typeNull; theContainer.dataHandle = nil; theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } return theErr; } \ No newline at end of file diff --git a/Source/C/cDocument.c b/Source/C/cDocument.c new file mode 100644 index 0000000..d4c466a --- /dev/null +++ b/Source/C/cDocument.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * DocumentAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a document according to the specified keyForm and returns the * corresponding document token * Inputs: classWanted = the element class desired (cDocument) * container = token for this element's container * containerClass = class of this element's container (typeNull/cWindow) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr DocumentAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused (classWanted, theRefCon) #endif ObjectTokenHandle theList; OSErr theErr = noErr; if (containerClass == cWindow) { if (IsValidForOne(keyForm, keyData)) { if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; PurgeNonDocuments(theList); } else return errAENoSuchObject; } else { switch (containerClass) { case cDocument: theList = (ObjectTokenHandle)container->dataHandle; if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; break; case typeNull: if (!(theList = MakeAllWindowsToken())) return memFullErr; PurgeNonDocuments(theList); break; default: return errAENoSuchObject; } switch (keyForm) { case formAbsolutePosition: theErr = GetAbsoluteWindow(keyData, &theList); break; case formName: theErr = GetNamedDocument(keyData, &theList); break; case formRelativePosition: case formTest: case formRange: case formPropertyID: default: return errAEBadKeyForm; break; } } if (!theList || !(*theList)->count || (theErr != noErr)) { DisposeHandle((Handle)theList); if (theErr == noErr) theErr = errAENoSuchObject; } else { theErr = AECreateHandleDesc(cDocument, (Handle)theList, resultToken); DisposeHandle((Handle)theList); } return theErr; } /* * DocPropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a document property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cDocument) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr DocPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused (classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-modifiable properties case pBestType: case pClass: case pDefaultType: case pIsModified: case pSelection: // Modifiable properties case pName: break; default: return errAEEventNotHandled; } theErr = HandToHand((Handle *)&theList); if (theErr != noErr) return theErr; (*theList)->property = propertyType; (*theList)->objclass = cDocument; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetDocumentData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the document * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetDocumentData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; return MakeDocumentObject(theWindow, theData); } /* * GetDocPropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the document's properties * Inputs: theWindow = the window associated with this object * theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetDocPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Boolean theBoolean = false; DescType theType; Str255 theString; AEDesc bestData; OSErr theErr; if (!theImage) return errAEReadDenied; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pClass: theType = cDocument; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pIsModified: theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pName: if (theImage) { BlockMove((*theImage)->file.name, theString, 64); if ((*theImage)->num) { AddChar(theString, ' '); AddNumber(theString, (*theImage)->num); } theErr = AEMakeIntlDesc(theString, &bestData); } break; case pSelection: theErr = MakeSelectionObject(theWindow, &bestData); break; default: return errAETypeError; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetDocPropertyData(theWindow, theProperty, theData) * * Purpose: Sets the data for the application's properties * Inputs: theWindow = the associated window * theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetDocPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Str255 theString; OSErr theErr; if (!theImage) return errAEWriteDenied; switch (theProperty) { case pName: theErr = AEExtractPString(theData, 0, theString); if (theErr == noErr) theErr = DoSetWindowTitle(theWindow, theString); break; default: theErr = errAEWriteDenied; break; } return theErr; } /* * MakeDocumentObject(theWindow, theObject) * * Purpose: Creates a document object descriptor for the given window * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeDocumentObject(WindowPtr theWindow, AEDesc *theObject) { long index = (theWindow == (WindowPtr)kAEAll) ? kAEAll : 0; AEDesc theKey, theContainer; OSErr theErr = noErr; WindowPtr window; if (!index) { for (window = GetFirstWindow(), index++; window && (window != theWindow); window = NextWindow(window)) if (FindImage(window)) index++; } theErr = AECreateDesc((index == kAEAll) ? typeAbsoluteOrdinal : typeLongInteger, (void *)&index, sizeof(long), &theKey); if (theErr == noErr) { theContainer.descriptorType = typeNull; theContainer.dataHandle = nil; theErr = CreateObjSpecifier(cDocument, &theContainer, formAbsolutePosition, &theKey, false, theObject); AEDisposeDesc(&theKey); } return theErr; } /* * MakeDocPropertyObject(theWindow, theProperty, theObject) * * Purpose: Creates a property object descriptor for the given drawing area's property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeDocPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = MakeDocumentObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * IsValidForOne(keyForm, keyData) * * Purpose: Determines if the given keyForm is valid for specifying a single object * for classes that can only contain a single element * Inputs: keyForm = the key form specified * keyData = the associated key data * Returns: true if this keyForm works for a single object; false otherwise * */ Boolean IsValidForOne(DescType keyForm, AEDesc *keyData) { long index; switch (keyForm) { case formAbsolutePosition: index = *(long *)*keyData->dataHandle; switch (keyData->descriptorType) { case typeLongInteger: if ((index < -1) || (index > 1)) return false; return true; case typeAbsoluteOrdinal: switch (index) { case kAEFirst: case kAELast: case kAEMiddle: case kAEAny: case kAEAll: return true; default: return false; } } case formName: case formRelativePosition: case formTest: case formRange: case formPropertyID: default: return errAEBadKeyForm; break; } } /* * PurgeNonDocuments(theList) * * Purpose: Scans through the given list of objects and removes any non-documents * Inputs: theList = a handle to an object token list * Returns: nothing * */ void PurgeNonDocuments(ObjectTokenHandle theList) { short i, newCount = 0, count = (*theList)->count; Ptr window; for (i = 0; i < count; i++) { window = (*theList)->object[i]; if (FindImage((WindowPtr)window)) (*theList)->object[newCount++] = window; } if (newCount != count) { SetHandleSize((Handle)theList, sizeof(ObjectToken) + (newCount - 1) * sizeof(Ptr)); (*theList)->count = newCount; } } /* * GetNamedDocument(keyData, theList) * * Purpose: Looks up a window from a text string * Inputs: keyData = descriptor containing search key data * theList = handle to the set of windows to search * Returns: an OSErr describing the result * */ OSErr GetNamedDocument(AEDesc *keyData, ObjectTokenHandle *theList) { short i, count = (**theList)->count; uchar theString[256]; WindowPtr *window; ImageHandle image; OSErr theErr; if (!count) return errAENoSuchObject; if ((theErr = AEExtractPString(keyData, 0, theString)) != noErr) return theErr; for (i = 0, window = (WindowPtr *)(**theList)->object; i < count; i++, window++) if (image = FindImage(*window)) if (EqualString((*image)->file.name, theString, false, false)) break; if (i == count) return errAENoSuchObject; DisposeHandle((Handle)*theList); if (!(*theList = MakeSingleObjectToken((Ptr)*window))) return memFullErr; return noErr; } /* * CountDocuments() * * Purpose: Counts the number of documents in the application * Inputs: none * Returns: the number of windows found * */ short CountDocuments(void) { ImageHandle image; short count = 0; for (image = gImageRoot; image; image = (*image)->next) count++; return count; } /* * IndexedDocument(index) * * Purpose: Locates a document in the linked list by index * Inputs: index = the number of the image in the list we seek * Returns: a pointer to the desired window, or nil if none found * */ WindowPtr IndexedDocument(short index) { ImageHandle theImage; short i; for (i = 1, theImage = gImageRoot; theImage && (i < index); i++, theImage = (*theImage)->next); return theImage ? (*theImage)->window : nil; } /* * GetDocumentIndex(theWindow) * * Purpose: Determines a document's numerical index in the linked list * Inputs: theWindow = a pointer to the document's window whose index we shall find * Returns: the index * */ short GetDocumentIndex(WindowPtr theWindow) { ImageHandle curImage; short i; for (i = 1, curImage = gImageRoot; curImage && ((*curImage)->window != theWindow); i++, curImage = (*curImage)->next); return curImage ? i : 1; } \ No newline at end of file diff --git a/Source/C/cDrawingArea.c b/Source/C/cDrawingArea.c new file mode 100644 index 0000000..6f257d5 --- /dev/null +++ b/Source/C/cDrawingArea.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * DrawingAreaAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a drawing area according to the specified keyForm and returns the * corresponding drawing area token * Inputs: classWanted = the element class desired (cDrawingArea) * container = token for this element's container * containerClass = class of this element's container (cWindow) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr DrawingAreaAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused (classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; OSErr theErr = noErr; if (IsValidForOne(keyForm, keyData)) { if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; PurgeNonDocuments(theList); } else return errAENoSuchObject; if (!theList || !(*theList)->count || (theErr != noErr)) { DisposeHandle((Handle)theList); if (theErr == noErr) theErr = errAENoSuchObject; } else { theErr = AECreateHandleDesc(cDrawingArea, (Handle)theList, resultToken); DisposeHandle((Handle)theList); } return theErr; } /* * DrawPropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a drawing area property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cDrawingArea) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr DrawPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused (classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-modifiable properties case pBestType: case pClass: case pDefaultType: // Modifiable properties case pBounds: case pColorTable: case pDrawQuality: case pScale: case pPalette: case pTransferMode: break; default: return errAEEventNotHandled; } theErr = HandToHand((Handle *)&theList); if (theErr != noErr) return theErr; (*theList)->property = propertyType; (*theList)->objclass = cDrawingArea; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetDrawingAreaData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the drawing area * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetDrawingAreaData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; return MakeDrawingAreaObject(theWindow, theData); } /* * GetDrawPropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the drawing area's properties * Inputs: theWindow = the window associated with this object * theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetDrawPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Boolean theBoolean = true; Point thePoint = { 0, 0 }; CTabHandle theColors; DescType theType; AEDesc bestData; short theShort; Rect theRect; OSErr theErr; if (!theImage) return errAEReadDenied; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pBounds: theRect = (*theImage)->wrect; theErr = AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), &bestData); break; case pClass: theType = cDrawingArea; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pColorTable: theColors = (CTabHandle)NewHandle(4); if (theColors) Palette2CTab((*theImage)->palette, theColors); theErr = AECreateHandleDesc(typeColorTable, (Handle)theColors, &bestData); DisposeHandle((Handle)theColors); break; case pDrawQuality: if ((*theImage)->quality == iqVHigh) theType = kAEDQVeryHigh; else if ((*theImage)->quality == iqHigh) theType = kAEDQHigh; else if ((*theImage)->quality == iqMedium) theType = kAEDQNormal; theErr = AECreateDesc(typeEnumerated, (void *)&theType, sizeof(DescType), &bestData); break; case pScale: theShort = ((long)Width(&(*theImage)->wrect) * 100) / Width(&(*theImage)->crect); theShort += ((long)Height(&(*theImage)->wrect) * 100) / Height(&(*theImage)->crect); theShort >>= 1; theErr = AECreateDesc(typeShortInteger, (void *)&theShort, sizeof(short), &bestData); break; case pPalette: switch ((*theImage)->npalette) { case plSys: theType = kAEPSystem; break; case plGrey: theType = kAEPGrayscale; break; case plImage: theType = kAEPImage; break; case plQuant: theType = kAEPQuantized; break; default: theType = typeWildCard; break; } theErr = AECreateDesc(typeEnumerated, (void *)&theType, sizeof(DescType), &bestData); break; case pTransferMode: theType = Dithered(theImage) ? kAEQDDitherCopy : kAEQDCopy; theErr = AECreateDesc(typeEnumerated, (void *)&theType, sizeof(DescType), &bestData); break; default: theErr = errAETypeError; break; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetDrawPropertyData(theWindow, theProperty, theData) * * Purpose: Sets the data for the drawing area's properties * Inputs: theWindow = the associated window * theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetDrawPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Rect theRect, oldRect; CTabHandle theColors; DescType theMode; short theShort; Fixed theFixed; OSErr theErr; if (!theImage) return errAEWriteDenied; switch (theProperty) { case pBounds: theErr = AEExtractQDRectangle(theData, 0, &theRect); if (theErr == noErr) theErr = DoSetDrawBounds(theImage, &theRect); break; case pColorTable: if (theData->descriptorType == typeColorTable) { theColors = (CTabHandle)theData->dataHandle; theErr = DoSetColorTable(theWindow, theColors); } else theErr = errAETypeError; break; case pDrawQuality: theErr = AEExtractEnumerated(theData, 0, &theMode); if (theErr == noErr) theErr = DoSetImageQuality(theImage, theMode); break; case pPalette: theErr = AEExtractEnumerated(theData, 0, &theMode); if (theErr == noErr) theErr = DoSetPalette(theWindow, theMode); break; case pScale: theErr = AEExtractShort(theData, 0, &theShort); if (theErr == noErr) { Rect monRect; theRect = (*theImage)->crect; theRect.right = theRect.left + ((theShort * Width(&theRect)) / 100); theRect.bottom = theRect.top + ((theShort * Height(&theRect)) / 100); OffsetRect(&theRect, -theRect.left, -theRect.top); GetActiveRect((*theImage)->dmon, &monRect); if (!Full(theImage)) monRect.top += gTitleBarHeight; if (Height(&theRect) > Height(&monRect)) { theRect.right = (long)theRect.right * (long)Height(&monRect) / (long)theRect.bottom; theRect.bottom = Height(&monRect); } if (Width(&theRect) > Width(&monRect)) { theRect.bottom = (long)theRect.bottom * (long)Width(&monRect) / (long)theRect.right; theRect.right = Width(&monRect); } oldRect = (*theImage)->wrect; (*theImage)->wrect = theRect; ResizeWindow(theImage); } break; case pTransferMode: theErr = AEExtractEnumerated(theData, 0, &theMode); if (theMode == kAEQDDitherCopy) theErr = DoSetImageDither(theImage, true); else if (theMode == kAEQDCopy) theErr = DoSetImageDither(theImage, false); else theErr = errAETypeError; break; default: theErr = errAEWriteDenied; break; } return theErr; } /* * MakeDrawingAreaObject(theWindow, theObject) * * Purpose: Creates a drawing area object descriptor for the given window * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeDrawingAreaObject(WindowPtr theWindow, AEDesc *theObject) { AEDesc theKey, theContainer; long index = kAEFirst; OSErr theErr = noErr; theErr = MakeWindowObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeAbsoluteOrdinal, (void *)&index, sizeof(long), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(cDrawingArea, &theContainer, formAbsolutePosition, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * MakeDrawPropertyObject(theWindow, theProperty, theObject) * * Purpose: Creates a property object descriptor for the given drawing area's property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeDrawPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = MakeDrawingAreaObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * DoSetColorTable(theWindow, theColors) * * Purpose: Sets the palette of the given window to the given set of colors * Inputs: theWindow = pointer to the window * theColors = a handle to the color table * Returns: an OSErr describing what went wrong * */ OSErr DoSetColorTable(WindowPtr theWindow, CTabHandle theColors) { ImageHandle theImage = FindImage(theWindow); PaletteHandle thePalette; if (!theImage) return errAEWriteDenied; if (thePalette = NewPalette((*theColors)->ctSize + 1, theColors, pmTolerant, 0)) { if ((*theImage)->palette) DisposePalette((*theImage)->palette); (*theImage)->palette = thePalette; SetPalette(theWindow, (*theImage)->palette, true); ActivatePalette(theWindow); if (theWindow == FWFrontWindow()) FWSelectWindow(theWindow); if (!GWOrigSize(theImage)) KillGWorld(theImage); (*theImage)->npalette = plNone; } else return memFullErr; return noErr; } /* * DoSetPalette(theWindow, thePalette) * * Purpose: Sets the palette of the given window to the given palette, * via DoSetColorTable * Inputs: theWindow = pointer to the window * thePalette = a constant specifying which palette to use * Returns: an OSErr describing what went wrong * */ OSErr DoSetPalette(WindowPtr theWindow, DescType thePalette) { ImageHandle theImage = FindImage(theWindow); PaletteHandle newPalette = nil, copyPalette; OSErr theErr = noErr; Boolean hadGWorld; short depth; if (!theImage) return errAENoSuchObject; hadGWorld = ((*theImage)->gworld != nil); depth = (*(*theImage)->dmon)->depth; switch (thePalette) { case kAEPSystem: newPalette = SystemPalette(depth); (*theImage)->npalette = plSys; break; case kAEPGrayscale: newPalette = GreyPalette(depth); (*theImage)->npalette = plGrey; break; case kAEPImage: newPalette = (*theImage)->ipalette; if (newPalette) (*theImage)->npalette = plImage; break; case kAEPQuantized: if ((*theImage)->depth < 16) break; if (depth > 8) depth = 8; if (!(*theImage)->qpalette || ((*(*theImage)->qpalette)->pmEntries != (1L << depth))) { theErr = DoQuantize(theImage, 1L << depth, &newPalette, nil); if ((theErr == noErr) && newPalette) { if ((*theImage)->qpalette) DisposePalette((*theImage)->qpalette); (*theImage)->qpalette = newPalette; } } newPalette = (*theImage)->qpalette; if (newPalette) (*theImage)->npalette = plQuant; break; default: return errAETypeError; } if (!newPalette && !(*theImage)->palette) newPalette = SystemPalette(depth), (*theImage)->npalette = plSys; if (newPalette) { copyPalette = NewPalette((*newPalette)->pmEntries, nil, pmTolerant, 0); if (copyPalette) { CopyPalette(newPalette, copyPalette, 0, 0, (*newPalette)->pmEntries); if ((*theImage)->palette) DisposePalette((*theImage)->palette); (*theImage)->palette = copyPalette; SetPalette(theWindow, (*theImage)->palette, true); ActivatePalette(theWindow); if (theWindow == FWFrontWindow()) FWSelectWindow(theWindow); if (hadGWorld && !GWOrigSize(theImage)) KillGWorld(theImage); } else theErr = memFullErr; } if (theErr == noErr && (*theImage)->npalette == plQuant && (*theImage)->gworld && !gThePrefs.origSize && (*(*theImage)->gworld->portPixMap)->pixelSize == (*theImage)->depth) theErr = ShrinkGWorld(theImage); return theErr; } /* * DoSetImageDither(theWindow, dither) * * Purpose: Sets the dither flag of the given image to the specified value * Inputs: theWindow = pointer to the window * dither = flag: true to dither the image; false otherwise * Returns: an OSErr describing what went wrong * */ OSErr DoSetImageDither(ImageHandle theImage, Boolean dither) { Rect theRect = (*theImage)->wrect; if (dither) (*theImage)->flags |= ifDithered; else (*theImage)->flags &= ~ifDithered; PushPort(); MySetPort((CGrafPtr)(*theImage)->window); InvalRect(&theRect); PopPort(); if ((*theImage)->gworld && !GWOrigSize(theImage)) KillGWorld(theImage); return noErr; } /* * DoSetImageQuality(theWindow, dither) * * Purpose: Sets the quality of the given image to the specified value * Inputs: theWindow = pointer to the window * dither = flag: true to dither the image; false otherwise * Returns: an OSErr describing what went wrong * */ OSErr DoSetImageQuality(ImageHandle theImage, DescType theQuality) { Rect theRect = (*theImage)->wrect; switch (theQuality) { case kAEDQVeryHigh: (*theImage)->quality = iqVHigh; break; case kAEDQHigh: (*theImage)->quality = iqHigh; break; case kAEDQNormal: (*theImage)->quality = iqMedium; break; default: return errAETypeError; } if (Dithered(theImage)) { PushPort(); MySetPort((CGrafPtr)(*theImage)->window); InvalRect(&theRect); PopPort(); if ((*theImage)->gworld) if (!GWOrigSize(theImage) || ((*(*theImage)->gworld->portPixMap)->pixelSize <= 8)) KillGWorld(theImage); } return noErr; } extern OSErr DoSetDrawBounds(ImageHandle theImage, Rect *theRect) { Rect oldRect = (*theImage)->wrect; (*theImage)->wrect = *theRect; ResizeWindow(theImage); if (!EqualSizeRect(&(*theImage)->wrect, &oldRect)) { PushPort(); MySetPort((CGrafPtr)(*theImage)->window); InvalRect(&(*theImage)->window->portRect); PopPort(); } return noErr; } \ No newline at end of file diff --git a/Source/C/cFile.c b/Source/C/cFile.c new file mode 100644 index 0000000..ebd473e --- /dev/null +++ b/Source/C/cFile.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * FileAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a document according to the specified keyForm and returns the * corresponding document token * Inputs: classWanted = the element class desired (cFile) * container = token for this element's container * containerClass = class of this element's container (cDocument) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr FileAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; OSErr theErr = noErr; if (IsValidForOne(keyForm, keyData)) { if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; } else return errAENoSuchObject; if (!theList || !(*theList)->count || (theErr != noErr)) { DisposeHandle((Handle)theList); if (theErr == noErr) theErr = errAENoSuchObject; } else { theErr = AECreateHandleDesc(cFile, (Handle)theList, resultToken); DisposeHandle((Handle)theList); } return theErr; } /* * FilePropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a file property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cFile) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr FilePropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-modifiable properties case pBestType: case pClass: case pDefaultType: case pIsStationeryPad: // Modifiable properties case pName: break; default: return errAEEventNotHandled; } theErr = HandToHand((Handle *)&theList); if (theErr != noErr) return theErr; (*theList)->property = propertyType; (*theList)->objclass = cFile; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetFileData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the file * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetFileData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; return MakeFileObject(theWindow, theData); } /* * GetFilePropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the file's properties * Inputs: theWindow = the window associated with this object * theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetFilePropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Boolean theBoolean = false; Handle theHandle; DescType theType; AEDesc bestData; FSSpec theSpec; long theLong; OSErr theErr; if (!theImage) return errAEReadDenied; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pClass: theType = cFile; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pIsStationeryPad: theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pName: theSpec = (*theImage)->file; theErr = GetFullPath(&theSpec, &theHandle); if ((theErr == noErr) && theHandle) { theLong = GetHandleSize(theHandle); SetHandleSize(theHandle, theLong + 4); if ((theErr = MemError()) == noErr) { BlockMove(*theHandle, (uchar *)*theHandle + 4, theLong); *(short *)*theHandle = smCurrentScript; *((short *)*theHandle + 1) = currentCurLang; theErr = AECreateHandleDesc(typeIntlText, theHandle, &bestData); } DisposeHandle(theHandle); } break; default: return errAETypeError; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetFilePropertyData(theWindow, theProperty, theData) * * Purpose: Sets the data for the application's properties * Inputs: theWindow = the associated window * theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetFilePropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Str255 theString; FSSpec theSpec; OSErr theErr; if (!theImage) return errAEReadDenied; switch (theProperty) { case pName: theErr = AEExtractPString(theData, 0, theString); if (theErr == noErr) { theErr = FSMakeFSSpec((*theImage)->file.vRefNum, (*theImage)->file.parID, theString, &theSpec); if ((theErr == noErr) || (theErr == fnfErr)) { (*theImage)->file = theSpec; theErr = noErr; } } break; default: theErr = errAEWriteDenied; break; } return theErr; } /* * MakeFileObject(theWindow, theObject) * * Purpose: Creates a file object descriptor for the given window * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeFileObject(WindowPtr theWindow, AEDesc *theObject) { AEDesc theKey, theContainer; long index = kAEFirst; OSErr theErr = noErr; theErr = MakeDocumentObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeAbsoluteOrdinal, (void *)&index, sizeof(long), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(cFile, &theContainer, formAbsolutePosition, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * MakeFilePropertyObject(theWindow, theProperty, theObject) * * Purpose: Creates a property object descriptor for the given files's property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeFilePropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = MakeFileObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } \ No newline at end of file diff --git a/Source/C/cImage.c b/Source/C/cImage.c new file mode 100644 index 0000000..ac05a94 --- /dev/null +++ b/Source/C/cImage.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * ImageAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds an image according to the specified keyForm and returns the * corresponding image token * Inputs: classWanted = the element class desired (cImage) * container = token for this element's container * containerClass = class of this element's container (cDrawingArea/cDocument) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr ImageAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; OSErr theErr = noErr; if (IsValidForOne(keyForm, keyData)) { if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; } else return errAENoSuchObject; if (!theList || !(*theList)->count || (theErr != noErr)) { DisposeHandle((Handle)theList); if (theErr == noErr) theErr = errAENoSuchObject; } else { theErr = AECreateHandleDesc(cImage, (Handle)theList, resultToken); DisposeHandle((Handle)theList); } return theErr; } /* * ImagePropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds an image property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cDocument) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr ImagePropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-modifiable properties case pBestType: case pClass: case pComments: case pCompression: case pDefaultType: case pDisplayTime: case pHasImageColorTable: case pHasQuantColorTable: case pImageColorTable: case pImageFormat: case pIsAborted: case pIsBanded: case pIsCompressed: case pIsCorrupt: case pIsCropped: case pLength: case pOriginalBounds: case pPixelDepth: case pQuantColorTable: // Modifiable properties case pBounds: break; default: return errAEEventNotHandled; } theErr = HandToHand((Handle *)&theList); if (theErr != noErr) return theErr; (*theList)->property = propertyType; (*theList)->objclass = cImage; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetImageData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the image * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetImageData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; return MakeImageObject(theWindow, theData); } /* * GetImagePropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the image's properties * Inputs: theWindow = the window associated with this object * theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetImagePropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Boolean theBoolean = true; CTabHandle theColors; Handle theHandle; DescType theType; AEDesc bestData; short theShort; long theLong; Rect theRect; OSErr theErr; if (!theImage) return errAEReadDenied; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pBounds: theRect = (*theImage)->crect; theErr = AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), &bestData); break; case pClass: theType = cImage; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pComments: theHandle = (*theImage)->comments; if (theLong = theHandle ? GetHandleSize(theHandle) : 0) theErr = HandToHand(&theHandle); if (!theLong || theErr == noErr) { if (theLong) SetHandleSize(theHandle, theLong + 4); else theHandle = NewHandle(4); if ((theErr = MemError()) == noErr) { if (theLong) BlockMove(*theHandle, *theHandle + 4, theLong); *(short *)*theHandle = smCurrentScript; *(short *)(*theHandle + 2) = currentCurLang; theErr = AECreateHandleDesc(typeIntlText, theHandle, &bestData); } DisposeHandle(theHandle); } break; case pCompression: theType = (*theImage)->compression; if (!(*theImage)->compression) theType = ' '; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pDisplayTime: theLong = (*theImage)->dtime; theErr = AECreateDesc(typeLongInteger, (void *)&theLong, sizeof(long), &bestData); break; case pHasImageColorTable: theBoolean = ((*theImage)->ipalette != nil); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pHasQuantColorTable: theBoolean = ((*theImage)->qpalette != nil); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pImageColorTable: theColors = (CTabHandle)NewHandle(4); if (theColors) Palette2CTab((*theImage)->ipalette, theColors); theErr = AECreateHandleDesc(typeColorTable, (Handle)theColors, &bestData); DisposeHandle((Handle)theColors); break; case pImageFormat: theType = (*theImage)->format->inType; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pIsAborted: theBoolean = Aborted(theImage); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsBanded: theBoolean = Banded(theImage); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsCompressed: theBoolean = ((*theImage)->compression != 0); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsCorrupt: theBoolean = Corrupt(theImage); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsCropped: theBoolean = Cropped(theImage); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pLength: theLong = GetHandleSize((*theImage)->data); theErr = AECreateDesc(typeLongInteger, (void *)&theLong, sizeof(long), &bestData); break; case pOriginalBounds: theRect = (*theImage)->grect; theErr = AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), &bestData); break; case pPixelDepth: theShort = (*theImage)->depth; theErr = AECreateDesc(typeShortInteger, (void *)&theShort, sizeof(short), &bestData); break; case pQuantColorTable: theColors = (CTabHandle)NewHandle(4); if (theColors) Palette2CTab((*theImage)->qpalette, theColors); theErr = AECreateHandleDesc(typeColorTable, (Handle)theColors, &bestData); DisposeHandle((Handle)theColors); break; default: theErr = errAETypeError; break; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetImagePropertyData(theWindow, theProperty, theData) * * Purpose: Sets the data for the images's properties * Inputs: theWindow = the associated window * theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetImagePropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Rect theRect; OSErr theErr; if (!theImage) return errAEWriteDenied; switch (theProperty) { case pBounds: theErr = AEExtractQDRectangle(theData, 0, &theRect); if (theErr == noErr) theErr = DoSetImageBounds(theImage, &theRect); break; default: theErr = errAEWriteDenied; break; } return theErr; } /* * MakeImageObject(theWindow, theObject) * * Purpose: Creates an image object descriptor for the given window * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeImageObject(WindowPtr theWindow, AEDesc *theObject) { AEDesc theKey, theContainer; long index = kAEFirst; OSErr theErr = noErr; theErr = MakeDocumentObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeAbsoluteOrdinal, (void *)&index, sizeof(long), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(cImage, &theContainer, formAbsolutePosition, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * MakeImagePropertyObject(theWindow, theProperty, theObject) * * Purpose: Creates a property object descriptor for the given images's property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeImagePropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = MakeImageObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * DoSetImageBounds(theImage, theRect) * * Purpose: Crops an image to the given bounds * Inputs: theImage = pointer to the image * theRect = the new bounds * Returns: an OSErr describing what went wrong * */ OSErr DoSetImageBounds(ImageHandle theImage, Rect *theRect) { Boolean delImage = true; if (Width(theRect) < 1) theRect->right = theRect->left + 1; if (Height(theRect) < 1) theRect->bottom = theRect->top + 1; /* if (Cropped(theImage) && !Banded(theImage) && ((*theImage)->format->inType == kPICTType) && ((*theImage)->compression == kJPEGCompression)) { picRect = (*(PicHandle)(*theImage)->data)->picFrame; if ((theRect->right > picRect.right) || (theRect->left < picRect.left) || (theRect->bottom > picRect.bottom) || (theRect->top < picRect.top)) { if (!MakeMemAvailable((*theImage)->desc.dataSize * 2)) return gIntError = errNoMemory, memFullErr; if (theData = UnwrapJPEG((*theImage)->data)) { if (newData = WrapJPEG(theData, (*theImage)->depth)) { for (image = gImageRoot; image; image = (*image)->next) if ((image != theImage) && ((*image)->data == (*theImage)->data)) delImage = false; if (delImage) DisposeHandle((*theImage)->data); (*theImage)->data = newData; (*theImage)->qrect = (*theImage)->grect; } else { DisposeHandle(theData); return gIntError = errNoMemory, memFullErr; } DisposeHandle(theData); } else return gIntError = errNoMemory, memFullErr; } }*/ (*theImage)->crect = *theRect; if (!GWOrigSize(theImage)) KillGWorld(theImage); (*theImage)->wrect = (*theImage)->crect; ScaleRect(&(*theImage)->wrect, (*theImage)->dmon, Full(theImage), gThePrefs.expandSmall); ResizeWindow(theImage); return noErr; } \ No newline at end of file diff --git a/Source/C/cPixelMap.c b/Source/C/cPixelMap.c new file mode 100644 index 0000000..c8d7bed --- /dev/null +++ b/Source/C/cPixelMap.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * PixelMapAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a pixel map according to the specified keyForm and returns the * corresponding pixel map token * Inputs: classWanted = the element class desired (cPixelMap) * container = token for this element's container * containerClass = class of this element's container (cImage) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr PixelMapAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; OSErr theErr = noErr; if (IsValidForOne(keyForm, keyData)) { if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; } else return errAENoSuchObject; if (!theList || !(*theList)->count || (theErr != noErr)) { DisposeHandle((Handle)theList); if (theErr == noErr) theErr = errAENoSuchObject; } else { theErr = AECreateHandleDesc(cPixelMap, (Handle)theList, resultToken); DisposeHandle((Handle)theList); } return theErr; } /* * PixelPropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a pixel map property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cFile) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr PixelPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-modifiable properties case pBestType: case pBounds: case pClass: case pDefaultType: case pPixelDepth: case pTransferMode: break; default: return errAEEventNotHandled; } theErr = HandToHand((Handle *)&theList); if (theErr != noErr) return theErr; (*theList)->property = propertyType; (*theList)->objclass = cPixelMap; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetPixelMapData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the pixel map * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetPixelMapData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; return MakePixelMapObject(theWindow, theData); } /* * GetPixelPropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the pixel map's properties * Inputs: theWindow = the window associated with this object * theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetPixelPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Boolean theBoolean = false; DescType theType; AEDesc bestData; short theShort; OSErr theErr; if (!theImage) return errAEReadDenied; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pBounds: theErr = AECreateDesc(typeQDRectangle, (void *)&(*theImage)->gworld->portRect, sizeof(Rect), &bestData); break; case pClass: theType = cPixelMap; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pPixelDepth: theShort = (*GetGWorldPixMap((*theImage)->gworld))->pixelSize; theErr = AECreateDesc(typeShortInteger, (void *)&theShort, sizeof(short), &bestData); break; default: return errAETypeError; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetPixelPropertyData(theWindow, theProperty, theData) * * Purpose: Sets the data for the pixel map's properties * Inputs: theWindow = the associated window * theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetPixelPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData) { #if applec #pragma unused(theData) #endif ImageHandle theImage = FindImage(theWindow); OSErr theErr; if (!theImage) return errAEWriteDenied; switch (theProperty) { default: theErr = errAEWriteDenied; break; } return theErr; } /* * MakePixelMapObject(theWindow, theObject) * * Purpose: Creates a pixel map object descriptor for the given window * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakePixelMapObject(WindowPtr theWindow, AEDesc *theObject) { AEDesc theKey, theContainer; long index = kAEFirst; OSErr theErr = noErr; theErr = MakeImageObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeAbsoluteOrdinal,(void *)&index, sizeof(long), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(cPixelMap, &theContainer, formAbsolutePosition, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * MakePixelPropertyObject(theWindow, theProperty, theObject) * * Purpose: Creates a property object descriptor for the given images's property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakePixelPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = MakePixelMapObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } \ No newline at end of file diff --git a/Source/C/cSelection.c b/Source/C/cSelection.c new file mode 100644 index 0000000..ad2fdea --- /dev/null +++ b/Source/C/cSelection.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * SelectionAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a selection according to the specified keyForm and returns the * corresponding selection token * Inputs: classWanted = the element class desired (cSelection) * container = token for this element's container * containerClass = class of this element's container (typeProperty) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr SelectionAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, keyForm, keyData, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; OSErr theErr = noErr; if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; if (!theList || !(*theList)->count || (theErr != noErr)) { DisposeHandle((Handle)theList); if (theErr == noErr) theErr = errAENoSuchObject; } else { theErr = AECreateHandleDesc(cSelection, (Handle)theList, resultToken); DisposeHandle((Handle)theList); } return theErr; } /* * SelPropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a file property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cSelection) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr SelPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, containerClass, theRefCon) #endif ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-modifiable properties case pBestType: case pClass: case pDefaultType: // Modifiable properties case pBounds: break; default: return errAEEventNotHandled; } theErr = HandToHand((Handle *)&theList); if (theErr != noErr) return theErr; (*theList)->property = propertyType; (*theList)->objclass = cSelection; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetSelectionData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the selection * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetSelectionData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; return MakeSelectionObject(theWindow, theData); } /* * GetSelPropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the selection's properties * Inputs: theWindow = the window associated with this object * theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetSelPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); DescType theType; AEDesc bestData; OSErr theErr; Rect theRect; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pClass: theType = cSelection; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pBounds: GetAntsSelection((*theImage)->ants, &theRect); theErr = AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), &bestData); break; default: return errAETypeError; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetSelPropertyData(theWindow, theProperty, theData) * * Purpose: Sets the data for the selection's properties * Inputs: theWindow = the associated window * theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetSelPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData) { ImageHandle theImage = FindImage(theWindow); Rect theRect; OSErr theErr; switch (theProperty) { case pBounds: theErr = AEExtractQDRectangle(theData, 0, &theRect); if (theErr == noErr && theImage) theErr = DoSetSelection(theImage, &theRect); break; default: theErr = errAEWriteDenied; break; } return theErr; } /* * MakeSelectionObject(theWindow, theObject) * * Purpose: Creates a selection object descriptor for the given window * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeSelectionObject(WindowPtr theWindow, AEDesc *theObject) { long index = kAEFirst; OSErr theErr = noErr; return MakeWinPropertyObject(theWindow, pSelection, theObject); } /* * MakeSelPropertyObject(theWindow, theProperty, theObject) * * Purpose: Creates a property object descriptor for the given selection's property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeSelPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = MakeSelectionObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } extern OSErr DoSetSelection(ImageHandle theImage, Rect *theRect) { SetAntsSelection((*theImage)->ants, theRect); ShowAnts((*theImage)->ants); return noErr; } \ No newline at end of file diff --git a/Source/C/cWindow.c b/Source/C/cWindow.c new file mode 100644 index 0000000..414da19 --- /dev/null +++ b/Source/C/cWindow.c @@ -0,0 +1 @@ +/*********************************************************/ /* This source code copyright (c) 1991-2001, Aaron Giles */ /* See the Read Me file for licensing information. */ /* Contact email: mac@aarongiles.com */ /*********************************************************/ #if THINK_C #include "THINK.Header" #elif applec #pragma load ":Headers:MPW.Header" #elif __MWERKS__ //#include "MW.Header" #else #include "JPEGView.h" #endif /* * WindowAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a window according to the specified keyForm and returns the * corresponding window token * Inputs: classWanted = the element class desired (cWindow) * container = token for this element's container * containerClass = class of this element's container (typeNull) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr WindowAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { #if applec #pragma unused(classWanted, theRefCon) #endif ObjectTokenHandle theList; OSErr theErr = noErr; switch (containerClass) { case cWindow: theList = (ObjectTokenHandle)container->dataHandle; if ((theErr = HandToHand((Handle *)&theList)) != noErr) return theErr; break; case typeNull: if (!(theList = MakeAllWindowsToken())) return memFullErr; break; default: return errAENoSuchObject; } switch (keyForm) { case formAbsolutePosition: theErr = GetAbsoluteWindow(keyData, &theList); break; case formName: theErr = GetNamedWindow(keyData, &theList); break; case formRelativePosition: case formTest: case formRange: case formPropertyID: default: return errAEBadKeyForm; break; } if (!theList || !(*theList)->count || (theErr != noErr)) { DisposeHandle((Handle)theList); if (theErr == noErr) theErr = errAENoSuchObject; } else { theErr = AECreateHandleDesc(cWindow, (Handle)theList, resultToken); DisposeHandle((Handle)theList); } return theErr; } /* * WinPropertyAccessor(classWanted, container, containerClass, keyForm, keyData, * resultToken, theRefCon) * * Purpose: Finds a window property and returns the corresponding property token * Inputs: classWanted = the element class desired (typeProperty) * container = token for this element's container * containerClass = class of this element's container (cWindow) * keyForm = the search key type * keyData = descriptor containing search key data * resultToken = descriptor containing the resulting token * theRefCon = reference constant * Returns: an OSErr describing the result * */ pascal OSErr WinPropertyAccessor(DescType classWanted, AEDesc *container, DescType containerClass, DescType keyForm, AEDesc *keyData, AEDesc *resultToken, long theRefCon) { ObjectTokenHandle theList = (ObjectTokenHandle)container->dataHandle; DescType propertyType; OSErr theErr; if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType)) return errAECantSupplyType; propertyType = *(DescType *)*keyData->dataHandle; switch (propertyType) { // Non-Modifiable properties case pBestType: case pClass: case pDefaultType: case pHasCloseBox: case pHasTitleBar: case pIsFloating: case pIsModal: case pIsResizable: case pIsZoomable: case pWindowType: // Modifiable properties case pBounds: case pFullScreen: case pIndex: case pIsZoomed: case pName: case pVisible: break; // Tricky properties case pSelection: return SelectionAccessor(classWanted, container, containerClass, keyForm, keyData, resultToken, theRefCon); default: return errAEEventNotHandled; } theErr = HandToHand((Handle *)&theList); if (theErr != noErr) return theErr; (*theList)->property = propertyType; (*theList)->objclass = cWindow; theErr = AECreateHandleDesc(typeProperty, (Handle)theList, resultToken); DisposeHandle((Handle)theList); return theErr; } /* * GetWindowData(theWindow, typeWanted, theData) * * Purpose: Extracts the data from the window * Inputs: theWindow = the window associated with this object * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetWindowData(WindowPtr theWindow, DescType typeWanted, AEDesc *theData) { if (typeWanted == typeWildCard) typeWanted = typeObjectSpecifier; if (typeWanted == typeBest) typeWanted = typeObjectSpecifier; if (typeWanted != typeObjectSpecifier) return errAECantSupplyType; return MakeWindowObject(theWindow, theData); } /* * GetWinPropertyData(theWindow, theProperty, typeWanted, theData) * * Purpose: Extracts the data from the window's properties * Inputs: theWindow = the window associated with this object * theProperty = the property wanted * typeWanted = the type we're asking for * theData = the data we save * Returns: an OSErr describing the result * */ OSErr GetWinPropertyData(WindowPtr theWindow, DescType theProperty, DescType typeWanted, AEDesc *theData) { Boolean theBoolean; ImageHandle theImage; DescType theType; Str255 theString; AEDesc bestData; long theLong; Rect theRect; OSErr theErr; switch (theProperty) { case pBestType: case pDefaultType: theType = typeObjectSpecifier; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pBounds: theRect = theWindow->portRect; GlobalRect(&theRect, theWindow); theErr = AECreateDesc(typeQDRectangle, (void *)&theRect, sizeof(Rect), &bestData); break; case pClass: theType = cWindow; theErr = AECreateDesc(typeType, (void *)&theType, sizeof(DescType), &bestData); break; case pHasCloseBox: theBoolean = HasGoAway(theWindow); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pHasTitleBar: theLong = GetWVariant(theWindow); theBoolean = (theLong != dBoxProc) && (theLong != altDBoxProc) && (theLong != plainDBox); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIndex: theLong = GetWindowIndex(theWindow); theErr = AECreateDesc(typeLongInteger, (void *)&theLong, sizeof(long), &bestData); break; case pIsFloating: theBoolean = WindowKind(theWindow) == floatingWindowKind; theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsZoomed: theBoolean = IsZoomed(theWindow); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pFullScreen: theImage = FindImage(theWindow); theBoolean = (theImage) ? (Full(theImage) != 0) : false; theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsModal: theBoolean = (WindowKind(theWindow) == dialogKind); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsResizable: theBoolean = (FindImage(theWindow) != nil); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pIsZoomable: theBoolean = (FindImage(theWindow) != nil) || (theWindow == GetStatWindow()); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pName: GetWTitle(theWindow, theString); theErr = AEMakeIntlDesc(theString, &bestData); break; case pSelection: theErr = MakeSelectionObject(theWindow, &bestData); break; case pVisible: theBoolean = WindowVisible(theWindow); theErr = AECreateDesc(typeBoolean, (void *)&theBoolean, sizeof(Boolean), &bestData); break; case pWindowType: theType = GetWRefCon(theWindow); theErr = AECreateDesc(typeEnumerated, (void *)&theType, sizeof(DescType), &bestData); break; default: return errAETypeError; } if (theErr != noErr) return theErr; if ((bestData.descriptorType == typeWanted) || (typeWanted == typeWildCard) || (typeWanted == typeBest)) theErr = AEDuplicateDesc(&bestData, theData); else theErr = AECoerceDesc(&bestData, typeWanted, theData); AEDisposeDesc(&bestData); return theErr; } /* * SetWinPropertyData(theWindow, theProperty, theData) * * Purpose: Sets the data for the window's properties * Inputs: theWindow = the associated window * theProperty = the property wanted * theData = the data to set it to * Returns: an OSErr describing the result * */ OSErr SetWinPropertyData(WindowPtr theWindow, DescType theProperty, AEDesc *theData) { WindowPtr behindWindow; Boolean theBoolean; WindowPtr window; Str255 theString; long theLong; Rect theRect; OSErr theErr; switch (theProperty) { case pBounds: theErr = AEExtractQDRectangle(theData, 0, &theRect); if (theErr == noErr) DoSetWindowBounds(theWindow, &theRect); break; case pFullScreen: theErr = AEExtractBoolean(theData, 0, &theBoolean); if ((theErr == noErr) && theWindow) DoSetWindowFull(theWindow, theBoolean); break; case pIndex: theErr = AEExtractLong(theData, 0, &theLong); if (theErr == noErr) { behindWindow = IndexedWindow(theLong); if ((behindWindow == GetFirstWindow()) || (behindWindow == FWFrontWindow())) ChangeActive(theWindow); else { for (window = GetFirstWindow(); window && (NextWindow(window) != behindWindow); window = NextWindow(window)); if (window) { SendBehind(theWindow, window); PaintOne((WindowPeek)theWindow, GetStrucRgn(theWindow)); CalcVis((WindowPeek)theWindow); } else theErr = errAEIndexTooLarge; } } break; case pIsZoomed: theErr = AEExtractBoolean(theData, 0, &theBoolean); if ((theErr == noErr) && theWindow) DoZoomWindow(theWindow, theBoolean); break; case pName: theErr = AEExtractPString(theData, 0, theString); if (theErr == noErr) theErr = DoSetWindowTitle(theWindow, theString); break; case pVisible: theErr = AEExtractBoolean(theData, 0, &theBoolean); if (theErr == noErr && theWindow) theErr = DoSetWindowVisible(theWindow, theBoolean); break; default: theErr = errAEWriteDenied; break; } return theErr; } /* * GetAbsoluteWindow(keyData, theList) * * Purpose: Looks up a window from an absolute position * Inputs: keyData = descriptor containing search key data * theList = handle to the set of windows to search * Returns: an OSErr describing the result * */ OSErr GetAbsoluteWindow(AEDesc *keyData, ObjectTokenHandle *theList) { short count = (**theList)->count; OSErr theErr = noErr; Ptr theWindow; long index; index = *(long *)*keyData->dataHandle; switch (keyData->descriptorType) { case typeLongInteger: if (!count) return errAENoSuchObject; if (index == 0) index++; if ((index < 1) || (index > count)) return errAENoSuchObject; theWindow = (**theList)->object[index - 1]; DisposeHandle((Handle)*theList); if (!(*theList = MakeSingleObjectToken(theWindow))) return memFullErr; break; case typeAbsoluteOrdinal: switch (index) { case kAEFirst: if (!count) return errAENoSuchObject; theWindow = (**theList)->object[0]; break; case kAELast: if (!count) return errAENoSuchObject; theWindow = (**theList)->object[count - 1]; break; case kAEMiddle: if (!count) return errAENoSuchObject; theWindow = (**theList)->object[count >> 1]; break; case kAEAny: if (!count) return errAENoSuchObject; theWindow = (**theList)->object[(count * Random()) >> 16]; break; case kAEAll: return noErr; case kStatWindowID: if (theWindow = (Ptr)GetStatWindow()) break; return gBadWindowID = index, errAENoSuchObject; case kCommentsWindowID: if (theWindow = (Ptr)GetCommentsWindow()) break; return gBadWindowID = index, errAENoSuchObject; case kHelpWindowID: if (theWindow = (Ptr)GetHelpWindow()) break; return gBadWindowID = index, errAENoSuchObject; case kSlideShowDialogID: if (theWindow = (Ptr)GetSlideOptionsWindow()) break; return gBadWindowID = index, errAENoSuchObject; case kPrefsDialogID: if (theWindow = (Ptr)GetPrefsWindow()) break; return gBadWindowID = index, errAENoSuchObject; default: return errAEBadKeyForm; } DisposeHandle((Handle)*theList); if (!(*theList = MakeSingleObjectToken(theWindow))) return memFullErr; break; default: return errAEBadKeyForm; } return noErr; } /* * GetNamedWindow(keyData, theWindow) * * Purpose: Looks up a window from a text string * Inputs: keyData = descriptor containing search key data * theList = handle to the set of windows to search * Returns: an OSErr describing the result * */ OSErr GetNamedWindow(AEDesc *keyData, ObjectTokenHandle *theList) { uchar theString[256], theTitle[256]; short i, count = (**theList)->count; WindowPtr *window; OSErr theErr; if (!count) return errAENoSuchObject; if ((theErr = AEExtractPString(keyData, 0, theString)) != noErr) return theErr; for (i = 0, window = (WindowPtr *)(**theList)->object; i < count; i++, window++) { GetWTitle(*window, theTitle); if (EqualString(theTitle, theString, false, false)) break; } if (i == count) return errAENoSuchObject; DisposeHandle((Handle)*theList); if (!(*theList = MakeSingleObjectToken((Ptr)*window))) return memFullErr; return noErr; } /* * CountWindows() * * Purpose: Counts the number of windows in the application * Inputs: none * Returns: the number of windows found * */ short CountWindows(void) { WindowPtr window; short count = 0; for (window = GetFirstWindow(); window; window = NextWindow(window)) count++; return count; } /* * IndexedWindow(index) * * Purpose: Returns the window associated with the given index * Inputs: index = the index * Returns: a pointer to the given window * */ WindowPtr IndexedWindow(short index) { WindowPtr theWindow; short count = 1; theWindow = GetFirstWindow(); for (; theWindow && (count < index); theWindow = NextWindow(theWindow)) count++; return (WindowPtr)theWindow; } /* * GetWindowIndex() * * Purpose: Gets the index of the given window * Inputs: theWindow = the window to look for * Returns: the index of the window * */ short GetWindowIndex(WindowPtr theWindow) { WindowPtr window; short count = 1; window = GetFirstWindow(); for (; window && (window != theWindow); window = NextWindow(window)) count++; return count; } /* * MakeWinPropertyObject(theWindow, theProperty, theObject) * * Purpose: Creates a window object descriptor for the given window's property * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeWinPropertyObject(WindowPtr theWindow, DescType theProperty, AEDesc *theObject) { AEDesc theKey, theContainer; OSErr theErr = noErr; theErr = MakeWindowObject(theWindow, &theContainer); if (theErr == noErr) { theErr = AECreateDesc(typeType, (void *)&theProperty, sizeof(DescType), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(typeProperty, &theContainer, formPropertyID, &theKey, false, theObject); AEDisposeDesc(&theKey); } AEDisposeDesc(&theContainer); } return theErr; } /* * MakeWindowObject(theWindow, theObject) * * Purpose: Creates a window object descriptor for the given window * Inputs: theWindow = pointer to the window, or nil for all windows * theObject = pointer to an AEDesc to store the result * Returns: an OSErr describing what went wrong * */ OSErr MakeWindowObject(WindowPtr theWindow, AEDesc *theObject) { AEDesc theKey, theContainer = { typeNull, nil }; OSErr theErr = noErr; DescType theType; long index; switch ((long)theWindow) { case kAEAll: index = (long)theWindow; theType = typeAbsoluteOrdinal; break; default: theType = typeLongInteger; index = GetWindowIndex(theWindow); break; } theErr = AECreateDesc(theType, (void *)&index, sizeof(long), &theKey); if (theErr == noErr) { theErr = CreateObjSpecifier(cWindow, &theContainer, formAbsolutePosition, &theKey, false, theObject); AEDisposeDesc(&theKey); } return theErr; } /* * MakeAllWindowsToken() * * Purpose: Creates a window token list specifying all open windows * Inputs: none * Returns: an ObjectTokenHandle containing the result * */ ObjectTokenHandle MakeAllWindowsToken(void) { short count = CountWindows(); ObjectTokenHandle theList; WindowPtr window, *item; if (theList = (ObjectTokenHandle)NewHandle(sizeof(ObjectToken) + (count - 1) * sizeof(Ptr))) { (*theList)->count = count; item = (WindowPtr *)(*theList)->object; for (window = GetFirstWindow(); window; window = NextWindow(window)) *item++ = window; } return theList; } /* * MakeSingleObjectToken(theObject) * * Purpose: Creates a window token list specifying the given object only * Inputs: theObject = pointer to the object record to specify * Returns: an ObjectTokenHandle containing the result * */ ObjectTokenHandle MakeSingleObjectToken(Ptr theObject) { ObjectTokenHandle theList; if (theList = (ObjectTokenHandle)NewHandle(sizeof(ObjectToken))) { (*theList)->count = 1; (*theList)->object[0] = theObject; } return theList; } /* * DoSetWindowBounds(theWindow, bounds) * * Purpose: Sets the bounds of the given window to the specified rectangle * Inputs: theWindow = the window to move/resize * bounds = the new bounds of the window * Returns: an OSErr describing the result * */ OSErr DoSetWindowBounds(WindowPtr theWindow, Rect *bounds) { ImageHandle theImage = FindImage(theWindow); MonitorHandle theMonitor; Rect newRect; RgnHandle theRgn; if (!EqualSizeRect(bounds, &theWindow->portRect)) { if (theImage && !Full(theImage)) { (*theImage)->wrect = *bounds; ResizeWindow(theImage); } else if (theWindow == GetHelpWindow()) { ResizeHelp(bounds); } else return errAEPrivilegeError; } newRect = theWindow->portRect; OffsetRect(&newRect, bounds->left - newRect.left, bounds->top - newRect.top); theMonitor = GetMostDevice(&newRect); if (theRgn = NewRgn()) { SetRectRgn(theRgn, newRect.left + 4, newRect.top - gTitleBarHeight + 4, newRect.right - 4, newRect.top - 4); SectRgn(theRgn, GetGrayRgn(), theRgn); if (EmptyRgn(theRgn)) NudgeWindowRect(&newRect, theMonitor); FWMoveWindow(theWindow, newRect.left, newRect.top, false); DisposeRgn(theRgn); } if (theImage) GetMinMaxMonitor(theImage); return noErr; } /* * DoSetWindowFull(theWindow, full) * * Purpose: Sets the full screen property of the given window * Inputs: theWindow = the window to move/resize * full = flag: true to make the window full-screen * Returns: an OSErr describing the result * */ OSErr DoSetWindowFull(WindowPtr theWindow, Boolean full) { ImageHandle theImage = FindImage(theWindow); WindowPtr behindWindow; GWorldPtr oldGWorld; Rect oldWRect; OSErr theErr; if (!theImage) return errAENotModifiable; oldWRect = (*theImage)->wrect; oldGWorld = (*theImage)->gworld; (*theImage)->gworld = nil; if (theWindow == FWFrontWindow()) behindWindow = nil; else for (behindWindow = GetFirstWindow(); behindWindow; behindWindow = NextWindow(behindWindow)) if (NextWindow(behindWindow) == theWindow) break; if (full) (*theImage)->flags |= ifFull; else (*theImage)->flags &= ~ifFull; theErr = MakeNewWindow(theImage, true, gThePrefs.expandSmall); (*theImage)->gworld = oldGWorld; if (theErr == noErr) { if ((*theImage)->palette) { SetPalette((*theImage)->window, (*theImage)->palette, true); ActivatePalette((*theImage)->window); } if (behindWindow) { SendBehind((*theImage)->window, behindWindow); FWShowWindow((*theImage)->window); } else ChangeActive((*theImage)->window); if (!EqualSizeRect(&(*theImage)->wrect, &oldWRect) && !GWOrigSize(theImage)) KillGWorld(theImage); } return theErr; } /* * DoSetWindowTitle(theWindow, theString) * * Purpose: Sets the title of the given window * Inputs: theWindow = the window to retitle * theString = the string to set it to * Returns: an OSErr describing the result * */ OSErr DoSetWindowTitle(WindowPtr theWindow, StringPtr theString) { ImageHandle theImage = FindImage(theWindow); MenuHandle windowMenu; short item; SetWTitle(theWindow, theString); if (!theImage) return noErr; item = GetDocumentIndex((*theImage)->window) + windowFirstItem - 1; (*theImage)->num = 0; if (windowMenu = GetMHandle(rWindowMenu)) SetItem(windowMenu, item, theString); return noErr; } extern OSErr DoSetWindowVisible(WindowPtr theWindow, Boolean visible) { if (visible) { FWShowWindow(theWindow); if (theWindow == FWFrontWindow()) ChangeActive(theWindow); } else FWHideWindow(theWindow); return noErr; } \ No newline at end of file