v13i026: ImageMagick - Graphics display programs, Part10/21
cristy at dupont.com
cristy at dupont.com
Fri May 24 13:18:46 AEST 1991
Submitted-by: cristy at dupont.com
Posting-number: Volume 13, Issue 26
Archive-name: imagemagic/part10
#!/bin/sh
# this is img.10 (part 10 of ImageMagick)
# do not concatenate these parts, unpack them in order with /bin/sh
# file ImageMagick/images/mandrill.miff.Z continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 10; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping ImageMagick/images/mandrill.miff.Z'
else
echo 'x - continuing file ImageMagick/images/mandrill.miff.Z'
sed 's/^X//' << 'SHAR_EOF' >> '_shar_tmp_.tmp' &&
M9+^/H7C3?(1ZOG=8D4<#PEKD9K-.0Y*_"B)CV&\0CE%SAP2^"FMZM7[(8OU8
M+W/$CE1P2VO/5A81P(XQ%IM,\3/BAT4,H"YV9GQ<,)-G3DZ2[@_B*S%GUDNZ
M"[DU_QL3*N5J4S]-9,U-)QH7%$8`[8"08Z=.6R>K@"!`JC71#:%4-2A&"NDJ
M)0#6#Z<.&0`D`%A])`"E/"$76232!Y4&V0?M$YX%5`(;%"D`=0R[6"V//P++
M>O4(XP.U!Z,[,(3>*6HDJPW;%TD"/`+E"$DB88.W,N`Y4P*Q'#$)Q!DR"40+
M)!(I$2QP!P_"*=8,Y!9KB7YU8#P=161G03TY%@@*4)25'JT+"`HUA!`1A4WU
M!J]-"#DZ4)$AMR+H7F]BTDSYBJ(@E`LCD3TH/2CV"!8`<V(F*84D?7T-"?\I
MDUD=%9@"EP($"`(`A8][!0]?"89 at 2JAUBG8(&AT`"@`Q`.62&Y)S2KLU[@\Q
M@(4"&I(R*9AL$Y)\1+4UFHG!;YX+X at 511>(K&U6&)5]P59'B=2B2#FY,DJI7
M^67Z=?!NGW&@<:%QG9#$3U]AU3WFCJIWM6;`<+APHWFGE-]"VG5Z`,=;JX2J
M=\1/G)"FE(9P:WIJ5[-.W%309\=;7'.NB8N/,1:94'Y^547A9LH9CU:!7""3
MAB5Q`'-*89)+*(9P()/\<?,K%PMD3L4`T0#`(D)5&@2V!N<=H"(#,WQV'F8_
M`!:&S4VV!K]?CPN``!0J\(2I(=4-#0!3)]\00X[O%E at GV0?_$"@`MRQ7`B(7
M<`NN#0\)EP+>%>@J&`H4%#^)GX$W)28"[A9$"UX"TP.I'QP`CF(<`-X2WPRR
M#><6I0XF`B`GR@\^`LX;;GTL)_H.S$K#&>D"62A64]EZS14?-S`P?Y,L:TTO
M[AZ$--<LWPP)./L;M8%7/=PT)S?M'`P<[1S2*'Q]QI$J/HT[#(4+:`D_HS2C
M-(!A,B<#:%<"3@*'AG$G,PG@!ML2_!`F)PU_&S-$`!8RV5?0*Q\7&`!^CT)1
M085V4+\?TA^9)'^)W`R-`F0`.A.YDSU6*V_\C#QL\ETC3']OXRO)9[<UZ1Z:
MB3]8+"G;CY*4*)+*&1!M+"E.>KQ/,$AV<?%N(G0G4XUII0">45&!>D:F`*MX
MD)!]D;X*KHFFE'=2N'"S3BISVG7Z=8=P\6[B*]QU:WJHD"MMLTZ&)=-\&77M
MAR2!1P#<5,U6?43U<]1OT90<6#<4&CI!D:!JC)1!D0PJEPO:E-E1#RJ+`.HS
M:65J98QA%BH@&ELGO at LM`(EDTAW(-.PZBT-!9:J3@(?5DNX73 at +%#P$15P7V
M"*",4@)/!=$#YQ'N%20%)0`8"H>4'@)3`@R0M(:[$)Q-3`NG!94?WCD=E=4#
M\P:D!2X`(R48)DPL-P`2`AH_LA`C`"PO%D2C'E`+-HO,18%3O"KF.%&42R)X
MCC&5Y!:^C"(;ISJ,'U@)4"+K'SH6FS-'-M(H*%Q')MP2K#H#A44W@&'70/TH
M98^.#3Q0:0I:`D$7M`?O<-E7)B>=B`H)QQN0:Y,+,PDU,;P@[BL9+7Y^!Q(B
M!,M'!$'T#T=1\4,8`*@U=R\2*3L8B%2#`&MDM04=7\]>2RA at 6?HS1I$[%3(I
MT33^DG\@Y"O5E`UN^6RC<-]"-6)1DN-UGD:-E223@)#8;X65=(NA<=)F5W*1
ME=Q4XV8.;N-UWW=F5^EVY9/'6X>5^64L*=QUM7ZZDWE;@95[D15<=3>](DUR
MU)2?6ZB0\EWB*VR6DD2F:(8EO2*:B9F5+"E$9N- at EVPE"%V2<B9"5A0JK"SF
M'1L7&AFXE2T`?"](<*=.\VK`8A1&K$C;'I@"DPTR`"8%3 at +.#>T7G8CJ$V,F
M0`)+!?84(P!'"G@&T!!*!1`/7C'<`[P.&2;V&$`I-R6I'A$`#`"*(-<0^1M[
M-=X-20#)6)D-O@\^`BT"+`+6"%$C8`85*"PG at P;V%,,9N0,D!18`/0`/'!$0
M#XG3<F`\J'1FE&XU6X]8)1(0HSH'#S03*A+7%DA"4QF4!<Y+"C at J-S169'9@
M/=F"&2LU5F6/'!K<5R at XPA_#3"4`2``19]\0-%`5%-\0(A?[D1DKN`P4%)@D
MEP(&``4`A5.//5MEF`+X!T\X#TPI8XP"&015.&0`O#7J at 665XF"'`H@/:S?N
M#]L,A at +%6@:72$NGE<"(QI/I'GEI#5P793J6N'"J5[F##4&Y<`R-P(Y]1"%9
M9X6:9!-VS0#C9N6.7',<DS]CPEJ':*MH%H*S3A:"PX[B"TEA:E<AD[U58);0
M9QR3)U-#=#(Y]7/`CM-OWW3[DM=%\ET;:\:3U6\Z>,@`+AK7'H8E1&;N#SH3
MCW6*/>Z2[AV5+I!C>07O';N5ZH$4*CTH,`"Z(E-]>@7CC/!&@6+I.C(`MQRJ
MD^H."P#@$?4(. at IM+Z\-[A>S!T8"ZA4$5SP"-B@*`#4*C at S\#[('[ALY`-D'
MA`8#`248V)63'Z,>0`7W`]('PQG5`QU%.A3/$Y8?YA3K&B*57 at M8@\(#ESM?
M.XB7S$KK&@J%/4[D%N4XZX5?6EIE]I7U!OP_3BBF`W9M-!-F+%Z4"`HP%5@)
M$1"QD@\1R5BZ0.DYA#RF4^)P1X1J/!@HAC4="``9G7N)- at H)NPXL`MV0Q0_G
M$L(?EP(+`,E'8V9^!04(+0"0`!$4_3*D6.4<TAT1*8P+FP6S+7$^M6&M898V
M_I/"D\I^AP+'9[!HB`+R72PIBP*N6<J3/Y;^C+!H1I'#E#YKAU92`0U!M57)
MDW=O=U+2DQ5<@VC8;^(KF0&'!+^4:WJ(E9-$JWB':&UYAW#8;RIUEI63`+AP
MEI5Y6VMZ"&2HD#(YLTZ=1L]$`Y at 4=#V79$X]ER"3VPQUD-P,BCV1E+H+<)9$
M9HECV15K-[5Z:3``:<8[^Q#$+.`=]3, at 0/A,P#1H?K,&]UU_8LM31#^X`U4P
M>XW=`R46ZA5O"W^'"@`G`B4820LY"NT3-`KV%`D)"PD9`"AX(0H'$D(+JTE>
M`KD"5 at O?&I!KCQ^/-.^0+`"`8\H:_Q3V%!\%3 at 4*`L`2C1UC#"D*IP5.!?$/
M3P6!#$D*P"AC-3(E*G#(&:@+]4MX=+B,60E!%9F3^XN>-H4^J`NE0X1'P$#$
M<>T<F`<J-P<_H8=#!)XVCQ_"C%%W;"0!%3$:-'<'$K61EU,D!>4#49-9B#:4
MNI?X#_D'`4L9``4`B%49`-H&"889`(``GXZC?3)+=@5SAUDX!AH5%\M@!U*.
M`/=2`I>,`O4<09$&A\<A'3J<F&F5C``J1I)$FHG6`)R#H'$[%2ADV),UDK=P
M7):21-)FLY2>6ZE7TWS8;Z60.FP;=<*4:Y:\F,1/7'.07A%TSW<G4Z<`NI,I
MEZ-Q%'309\68AVC_DJI7M2(<D^22[)+R70*8-Q2+CZF5AB4Q*7)*)$R-`IQ#
M!$;;F&]DO).7"\`B[GJ5-GR6C#9#`+\LFC:4`ML>_4JY!DYG>@7Z%X\+."@I
M`)TMJC75#6,F)@7B.F\+EP*?+0(('Q?0*U0""PDD!>H#2PO.!YP>VQ<V-^@#
M("=>`B**300.E4L$50NE#ADF.Q2- at OD"M0\4".8^G`Y"E,\#]`0-`OT!B1_H
M`]4(\A?1*?@&T`BH+NJ%,##5#$HVD6SKA=B+D2$:!9Z7*9DY))H#F`<\)'L-
M"SCM'MB+-1BXDF<X%&A#D*XC@(XI&!QG0`#YBB]E2051D#9^S0^F(*,T5P(6
M&8-\*`CY!XN#&``1`-9!+@#4E+@&*P!S`%>0\P\VC5M"D)0D4G0%&P37("",
M=9:,`C at 4\EV+`M*4XBL!EZ`ND93,,_QV&&OB*V&2AG"GF,AG=)E1:K=PMFX;
M:X]6:W(L;0YNO4CP;E]KO2*X<#)T4P%K<XV5EY5K>A:"P78REWD`<DISEKU5
MTY>.E3<4PY0$4_(KY6:EE`F8*Q>@+@>8U90R.8T"S&'&DV at PI9A$9M4T04H#
M0/@Z&TI\-TLH>"^-`/0/Z!V$`-]SK4*5-DMDN6QN)B($*`"$2=1>-2AB9M4-
M;PNN(1(4MPSJ%2D%^YB#-N<8S0<%`-D1])0[,E<%.IB:!N@#/P0E`.<(7 at G-
M$34"U'02.'<,<R$9*)\.Z`,7"BX`VA)4)<H/Q!+GE=(#5 at NF#?P/BPL'!0,!
MSR?$&54#BBR!5L0H?Y,=-QL1^Q@#<4($=@X<D=E`TS_X!JYIJ`N8!R<WR6C`
M0&(A)B^SDGYC[1S!:K<R*P`Y)'5"6F7O<.0Y%)4K2A<3"@G_*3\*=9<0">V&
M)BF9CB\`XCKV%(\+YY;VAOP'V6"5`J%]!0CK1H0`&P"$`,E7SR`?!/,'YT&/
M3B1,LDR:E88E'QO]6`>7N3614X8EM54]5E"+QR&#<IU/,YJLF-64<);_C#^7
MC94H9,"(,'0CD[-.KFBED/`E_Y)#EO&7R&)KEJ-W_)?RD]&3%Y/UE]Q4DP`N
M<Y:5E977E]!G#4&<0\T``9>8F=>7AB6EF)^9`TTSFO=2GE'8(-N8BY1?,&>:
M&@1H5;14FYG@*]4TK3S"(;29%106AN9J^Q"_?-L>%!1OCVQC1@!'E0P`)P`7
M$R46MQRY`[P,MQS9$24`89<&&T`"*04!".`#G at 59!2$7]Y0>`ND(;H$6"N0#
M#0+H`Q8`1`!G"L(#H(Q#!%`%`P$+,:$@CAU!?CT"[Q8V`GZ71`L%"?,6IP71
M`_46I(%("WJ7RDM!(QXDQ"B94K,+NFI?;/`K]0Z:C1L1_Y6F`SI`-)F]C*LR
MQRBP$#E/:V(T5O4&7'RW,M&`P$`\D`N6L8T9,>T1PW0<%9.,V%=D"Q<%6T],
M)1P5#(RX!K$#KB$Z48\+SX<:`!\`:G#W"&(`OPPO`&4`&`"#`(@/\AS2'R=2
MD%7]46Y)TXTW%`&79%5(2\.3:IJW-=YI at 5QWBCL5V)1$FI)$!5,4=&&:!5GE
MDA=ED%Y-DFN6^642&"U,9UF]3PU!8VLVC/>7CI709R&3S0#7;]!GF97<=5V6
M:E>,`-QU9YEPEH=H<I709V&2XBO]6`&7*YMTEC&;F)FR(M.8QBQY6\@`D0+M
M'695S0!U/D%*!$!BE?)=E39_('8^A@#_4 at X:2SC,D.J4@%4U*#TH07\%$AD5
M;Y0[!0`1YQB+"^(Z[!3H*@((PIF+FGN-,C$-`',G1`JU#Q0`[@/5#S8^00+Z
M"!``G at 71$+0'[Q-""]@77@*2(#(%S)7E`^\3P#IT8X\?BXWE)[@S[!H6"J1%
M9DOF%"9)S at G:,EP'/7W]"%]LCAU$`2H2FAIX"HT\CQT)"A1H>(XWD%D)P3D8
M$==P8#7_F>@GL063!24O?`UGF#D6+)#W47%]M#K8/V&83B46,=T2O1(J`"(`
MBPP.*!)IQANO:L(?)H3^2O%2M0^!24%_8F9C1)`]D``*`$%B,2P8`"H`R%EW
M#@=[^P?2'PERO4&1`B1,TYA>9[,MEC:7E,`B,YKB#>(KB6-O"I$`<IEPE=.8
MUY?B8,.3)4R?F:!Q-Q05=-]F=VK?F].77F>Y5)"0J&C!F+R8H'&6E7R0RGZS
M3BM&'YO<=>(KTY?!D[U5I9 at CFY,`X9N:E2M&-Q0$4V:9.!1$9@)2,YK.6-N8
M.!0-&:J9S#-X+Y,`U33^43(Y04J&`CH3%QO0+($E%QCE:D,Q<R\<>LYT,PG[
M$$%__DH?FKB7S`?5#;<<&`KA`\`@T at T`$>4<&``$"+4#@078!]$0B0L.*"X`
M)`#2E<X#1G4Z"H8,*P`[`(X,A`:Z!SD%%`"?!ZL-<R'/`\0<]7E*!#\%?0Q9
M-JH;\1<$`7<$KQS1$!<`GP6T.<,#PP,+`*L09B$N)-@$&!%H-:L+G1)+(O4&
M;DAW6N(X%WDN),LHF`=@-981E1&P"_\W at I.-@GEMH72$-*H%E6HP,'"(S(#1
M$>@1BPRK.]R:\@/"'WR"^A1PE">$FU4<@_8(_4IG"K<&7DJ,68\`%@"9"KLE
M#0`M`%X`"@"R+:-LL(@D4B-2_TLB7@\JBP+]C&B:RW-OFA*8L36(`@*<DI3H
M3?R,9IJ&)=L,+IO,`/N;:##5E*N8(TSC8,EG,CF=3Z"/,BGTFRIS37(!;`]N
MVIO3E_N;Q)2X<,*4:I8NE\:8^V0^'[=(W'5;F at 13+)M>FI29,YK]FRN;V5'3
MF)(`*9LD3#]6DEK7;V at PUTT..3N;O4%C964`*Q>L85LXE"Y`,11&@27T5GD%
MZX94B.<J:2]CC3THBBX4%.<2S`<%`"@`M0.3#<J9P"`B*>H5'P"!!;^7!@@;
M%/8410(J`%M/1 at KG&-8-QR!NEQ(`V@/K&K00V`.H'!D`1`L'"<,#M0\@``$!
M64\1E1"9S at D4G=,:(I7S%H(PX!?I%M<3R@^7`J:6LAP]BT($DY>]FNN%$1#T
M'54QICHV>/)0?F-%-J8Z+B3D%=0,Z!^P"U at TK"XPG6XU*'!+=]$14H*;=#V5
M\Q/20%$%BVR4:T`"3"5"/KD"2`1`%R>$KI'F"#,)]@,&`/00-(L/,R82<0!_
M!?"6(18A`,H`C@!B`*J1"1HJ:-U,O4$`FW(WD@(TF at -`H9R["^R2C`+3C6!9
MFHF5B7*5V91`D61 at TYP-;D&189)'EV)A/58&`SJ;>V!BFD1F29)&EE,!H(]@
MFBISM7X4=.:;)9OUFR6;CH_7;V)S<TK09^T=UYC at F[=P+C)J5]YI:)H]5L8`
M9E4#33<G*QDAFY``E@"PG/=7JC38(')#:%477^- at W`[?DA,J90`+DIAMGR+F
M'8$E;Y1"93$`B0O1'Q44S3O;'FZ/5P4:`A,`)YS=`Y,-"`#B. at L`PIG/#5>;
M#0`"`,*-`@`3,D@%V1&_#XHVB9+N%D4"RP;/,AX"]1/**;0S("<O!3D*U@@@
M!4*8_W#V$]`1%S_1`^43(@#GE5,"TA!^!>8()P45`"HF[1+#`_,6$@(Y"!@1
MY3@')5J)UPQ"!-EZ$A#27YH#JPL8>2:5V7HTF2H2S9J]5^P_'`7,,;\I.22F
M`CH45(GW4348"P_9$B8Z8Y-JAR@:Y7%)!1&63"4E&\8.MHOID(HF[AN9)1,4
MR4=@`+N;ZD:E5,-+`P#B'+(MQ"SRAO@'&P3534QP^YMU/CV;\P?\6$=+[)*@
M:HT"&I)$9FV5_(P]GL`B<TKN#]R;N37N#RYS:Y90"<\`UV\_EF.:/9<"F/EN
MY9)C<R-,/&.7E5*:.YLTEV4`8I:1F;R<8IJ8G<"4PYR3`-2<8YJ':/N7PYS7
MEZ><SIQGFCJ;-EV]8"EYEC8-&9``8E69G3<GD`)!2MU,W4:+`L0L;#"7F&``
M8424`D0X&$P?0.V<'1D4%..,08XI`#(`"X8U;[:+]0A2!BXO!QL'&QD`"`!A
MFQH"LBR)GER;@@6C`I4->XVP#2F)[0,F!=(0!@`?`"4*B`;?*2$*Y)!>`@0Q
M55.J(J8-GP<V!0<)IASQ%JL'>`8M,.84P@/I""\+[AL at GN$#S@?RG0H`#@'`
MGL&>PIZM`L2>PYX-`0P!QI[)GLJ>RY[,GLV>SI[/GLF>R)[0GM.>U)[5GM:>
MQI[2GM>>QY[;GL&>#`'>G@``X&<.`0X=R)[?GL.>V9[+GN>>RI[GGNF>VI[M
-GL*>[)[NGO&>\I[4G@'>
`
end
SHAR_EOF
echo 'File ImageMagick/images/mandrill.miff.Z is complete' &&
echo 'uudecoding file ImageMagick/images/mandrill.miff.Z' &&
uudecode < _shar_tmp_.tmp && rm -f _shar_tmp_.tmp &&
chmod 0700 ImageMagick/images/mandrill.miff.Z ||
echo 'restore of ImageMagick/images/mandrill.miff.Z failed'
Wc_c="`wc -c < 'ImageMagick/images/mandrill.miff.Z'`"
test 204043 -eq "$Wc_c" ||
echo 'ImageMagick/images/mandrill.miff.Z: original size 204043, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/import.c ==============
if test -f 'ImageMagick/import.c' -a X"$1" != X"-c"; then
echo 'x - skipping ImageMagick/import.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/import.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/import.c' &&
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% IIIII M M PPPP OOO RRRR TTTTT %
% I MM MM P P O O R R T %
% I M M M PPPP O O RRRR T %
% I M M P O O R R T %
% IIIII M M P OOO R R T %
% %
% %
% Import X11 image to a machine independent format. %
% %
% %
% %
% Software Design %
% John Cristy %
% January 1991 %
% %
% %
% Copyright 1991 E. I. Dupont de Nemours & Company %
% %
% Permission to use, copy, modify, distribute, and sell this software and %
% its documentation for any purpose is hereby granted without fee, %
% provided that the above Copyright notice appear in all copies and that %
% both that Copyright notice and this permission notice appear in %
% supporting documentation, and that the name of E. I. Dupont de Nemours %
% & Company not be used in advertising or publicity pertaining to %
% distribution of the software without specific, written prior %
% permission. E. I. Dupont de Nemours & Company makes no representations %
% about the suitability of this software for any purpose. It is provided %
% "as is" without express or implied warranty. %
% %
% E. I. Dupont de Nemours & Company disclaims all warranties with regard %
% to this software, including all implied warranties of merchantability %
% and fitness, in no event shall E. I. Dupont de Nemours & Company be %
% liable for any special, indirect or consequential damages or any %
% damages whatsoever resulting from loss of use, data or profits, whether %
% in an action of contract, negligence or other tortious action, arising %
% out of or in connection with the use or performance of this software. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Import is an X Window System window dumping utility. Import allows X
% users to store window images in a specially formatted dump file. This
% file can then be read by the Display utility for redisplay, printing,
% editing, formatting, archiving, image processing, etc. The target
% window can be specified by id or name or be selected by clicking the
% mouse in the desired window. The keyboard bell is rung once at the
% beginning of the dump and twice when the dump is completed.
%
% The import program command syntax is:
%
% Usage: import [options ...] file
%
% Where options include:
% -border include image borders in the output image
% -display server X server to contact
% -frame include window manager frame
% -id number select window with this resource id
% -monochrome transform image to black and white
% -name name select window with this WM_NAME property
% -root select root window
% -scene image scene number
% -screen select image from root window
%
% Change '-' to '+' in any option above to reverse its effect.
% For example, +frame means do not window manager frame.
%
% Specify 'file' as '-' for standard input or output.
%
%
*/
X
/*
X Include declarations.
*/
#include "display.h"
#include "image.h"
#include "X.h"
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% E r r o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Function Error displays an error message and then terminates the program.
%
% The format of the Error routine is:
%
% Error(message,qualifier)
%
% A description of each parameter follows:
%
% o message: Specifies the message to display before terminating the
% program.
%
% o qualifier: Specifies any qualifier to the message.
%
%
*/
void Error(message,qualifier)
char
X *message,
X *qualifier;
{
X (void) fprintf(stderr,"%s: %s",application_name,message);
X if (qualifier != (char *) NULL)
X (void) fprintf(stderr," (%s)",qualifier);
X (void) fprintf(stderr,".\n");
X exit(1);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% U s a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Procedure Usage displays the program usage;
%
% The format of the Usage routine is:
%
% Usage(message)
%
% A description of each parameter follows:
%
% message:Specifies a specific message to display to the user.
%
*/
static void Usage(message)
char
X *message;
{
X char
X **p;
X
X static char
X *options[]=
X {
X "-border include image borders in the output image",
X "-display server X server to contact",
X "-frame include window manager frame",
X "-id number select window with this resource id",
X "-monochrome transform image to black and white",
X "-name name select window with this WM_NAME property",
X "-root select root window",
X "-scene image scene number",
X "-screen select image from root window",
X (char *) NULL
X };
X if (message != (char *) NULL)
X (void) fprintf(stderr,"Can't continue, %s.\n\n",message);
X (void) fprintf(stderr,"Usage: %s [options ...] file\n",application_name);
X (void) fprintf(stderr,"\nWhere options include:\n");
X for (p=options; *p != (char *) NULL; p++)
X (void) fprintf(stderr," %s\n",*p);
X (void) fprintf(stderr,
X "\nChange '-' to '+' in any option above to reverse its effect.\n");
X (void) fprintf(stderr,
X "For example, +frame means do not include window manager frame.\n");
X (void) fprintf(stderr,"\nSpecify 'file' as '-' for standard output.\n");
X exit(1);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% M a i n %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
int main(argc,argv)
int
X argc;
X
char
X *argv[];
{
X char
X *filename,
X *option,
X *server_name,
X *user_default;
X
X Display
X *display;
X
X Image
X *image;
X
X int
X i;
X
X unsigned int
X borders,
X frame,
X j,
X monochrome,
X scene,
X screen;
X
X Window
X client_window,
X root_window,
X target_window;
X
X /*
X Display usage profile if there are no command line arguments.
X */
X application_name=(*argv);
X if (argc < 2)
X Usage((char *) NULL);
X /*
X Connect to X server.
X */
X server_name=(char *) NULL;
X for (i=1; i < argc; i++)
X {
X /*
X Check command line for server name.
X */
X option=argv[i];
X if ((strlen(option) > 1) && ((*option == '-') || (*option == '+')))
X if (strncmp("dis",option+1,3) == 0)
X {
X /*
X User specified server name.
X */
X i++;
X if (i == argc)
X Usage("missing server name on -display");
X server_name=argv[i];
X break;
X }
X }
X display=XOpenDisplay(server_name);
X if (display == (Display *) NULL)
X Error("unable to connect to X server",XDisplayName(server_name));
X root_window=XRootWindow(display,XDefaultScreen(display));
X /*
X Get X defaults.
X */
X user_default=XGetDefault(display,application_name,"borders");
X borders=IsTrue(user_default);
X user_default=XGetDefault(display,application_name,"frame");
X frame=IsTrue(user_default);
X user_default=XGetDefault(display,application_name,"monochrome");
X monochrome=IsTrue(user_default);
X user_default=XGetDefault(display,application_name,"scene");
X scene=(user_default == (char *) NULL) ? 0 : atoi(user_default);
X user_default=XGetDefault(display,application_name,"screen");
X screen=IsTrue(user_default);
X /*
X Check command syntax.
X */
X filename=(char *) NULL;
X target_window=(Window) NULL;
X for (i=1; i < argc; i++)
X {
X option=argv[i];
X if ((strlen(option) < 2) || ((*option != '-') && (*option != '+')))
X filename=argv[i];
X else
X switch(*(option+1))
X {
X case 'b':
X {
X borders=(*option == '-');
X break;
X }
X case 'd':
X {
X /*
X User specified server name.
X */
X i++;
X if (i == argc)
X Usage("missing server name on -display");
X server_name=argv[i];
X break;
X }
X case 'h':
X {
X Usage((char *) NULL);
X break;
X }
X case 'f':
X {
X frame=(*option == '-');
X break;
X }
X case 'i':
X {
X i++;
X if (i == argc)
X Usage("missing id on -id");
X option=argv[i];
X target_window=(Window) strtol(option,(char **) NULL,0);
X break;
X }
X case 'm':
X {
X monochrome=(*option == '-');
X break;
X }
X case 'n':
X {
X i++;
X if (i == argc)
X Usage("missing name on -name");
X option=argv[i];
X target_window=XWindowByName(display,root_window,option);
X if (target_window == (Window) NULL)
X (void) fprintf(stderr,"No window with name %s exists!\n",option);
X break;
X }
X case 'r':
X {
X target_window=root_window;
X break;
X }
X case 's':
X {
X if (strncmp("scene",option+1,4) == 0)
X {
X i++;
X if (i == argc)
X Usage("missing scene on -scene");
X scene=atoi(argv[i]);
X }
X else
X if (strncmp("screen",option+1,4) == 0)
X screen=(*option == '-');
X else
X Usage((char *) NULL);
X break;
X }
X default:
X Usage((char *) NULL);
X }
X }
X if (filename == (char *) NULL)
X Usage("missing an image file name");
X /*
X If the window is not specified, let the user choose one with the mouse.
X */
X if (target_window == (Window) NULL)
X target_window=XSelectWindow(display,root_window);
X client_window=target_window;
X if (target_window != root_window)
X if (XGetGeometry(display,target_window,&root_window,&i,&i,&j,&j,&j,&j) != 0)
X {
X /*
X Get client window.
X */
X client_window=XClientWindow(display,target_window);
X if (!frame)
X target_window=client_window;
X }
X image=XReadImage(display,root_window,target_window,client_window,screen,
X borders);
X if (image == (Image *) NULL)
X exit(1);
X image->scene=scene;
X if (monochrome)
X {
X register unsigned int
X bit;
X
X /*
X Convert image to monochrome PseudoColor class.
X */
X (void) QuantizeImage(image,2,0,False,True);
X bit=Intensity(image->colormap[0]) > Intensity(image->colormap[1]);
X image->colormap[bit].red=0;
X image->colormap[bit].green=0;
X image->colormap[bit].blue=0;
X image->colormap[!bit].red=255;
X image->colormap[!bit].green=255;
X image->colormap[!bit].blue=255;
X }
X (void) strcpy(image->filename,filename);
X (void) fprintf(stderr,"[%d] %s %dx%d\n",image->scene,image->filename,
X image->columns,image->rows);
X (void) WriteImage(image);
X DestroyImage(image);
X return(False);
}
SHAR_EOF
chmod 0755 ImageMagick/import.c ||
echo 'restore of ImageMagick/import.c failed'
Wc_c="`wc -c < 'ImageMagick/import.c'`"
test 14198 -eq "$Wc_c" ||
echo 'ImageMagick/import.c: original size 14198, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/import.man ==============
if test -f 'ImageMagick/import.man' -a X"$1" != X"-c"; then
echo 'x - skipping ImageMagick/import.man (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/import.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/import.man' &&
.ad l
.nh
.TH IMPORT 1 "1 January 1991" "X Version 11"
.SH NAME
import - dump an image of an X window as MIFF
.SH SYNOPSIS
.B "import"
[ \fIoptions\fP ... ] \fIfile\fP
.SH DESCRIPTION
.PP
.I Import
is an X Window System window dumping utility.
.I Import
allows X users to store window images in a specially formatted dump
file. This file can then be read by the \fIDisplay\fP utility for
redisplay, printing, editing, formatting, archiving, image processing, etc.
The target window can be specified by id or name or be selected by clicking
the mouse in the desired window. The keyboard bell is rung once at the
beginning of the dump and twice when the dump is completed.
.SH EXAMPLES
.PP
To select a X window and save it in the MIFF format to a file on disk
titled window.ps, use:
.PP
X import window.ps
.PP
To save the entire X server screen in the MIFF format to a file on disk
titled root.ps, use:
.PP
X import -root root.ps
.SH OPTIONS
\fIImport\fP options can appear on the command line or in your X resources
file (see X(1)). Options on the command line supercede values specified
in your X resources file.
.TP 5
.B "-border"
include image borders in the output image.
.TP 5
.B "-display \fIhost:display[.screen]\fP"
specifies the X server to contact; see \fBX(1)\fP.
.TP 5
.B "-frame"
include window manager frame.
.TP 5
.B "-id \fIvalue\fP"
select window with this resource id.
X
See \fBxwininfo(1)\fP for one way of listing window resource id's.
.TP 5
.B "-monochrome"
transform image to black and white.
.TP 5
.B "-name \fIname\fP"
select window with this WM_NAME property.
X
See \fBxprop(1)\fP for one way of listing window property's.
.TP 5
.B "-root"
select root window.
.TP 5
.B "-scene"
image scene number.
.TP 5
.B "-screen"
This option indicates that the GetImage request used to obtain the image
should be done on the root window, rather than directly on the specified
window. In this way, you can obtain pieces of other windows that overlap
the specified window, and more importantly, you can capture menus or other
popups that are independent windows but appear over the specified window.
.PP
Change \fI-\fP to \fI+\fP in any option above to reverse its effect. For
example \fB+frame\fP means do include window manager frame.
.PP
Specify \fIfile\fP as \fI-\fP for standard input or output.
.PP
.SH ENVIRONMENT
.PP
.TP 5
.B DISPLAY
To get the default host, display number, and screen.
.SH SEE ALSO
XX(1), display(1), XtoPS(1)
.SH COPYRIGHT
Copyright 1991 E. I. Dupont de Nemours & Company
.PP
Permission to use, copy, modify, distribute, and sell this software and
its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of E. I. Dupont de Nemours
& Company not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission. E. I. Dupont de Nemours & Company makes no representations
about the suitability of this software for any purpose. It is provided
"as is" without express or implied warranty.
.PP
E. I. Dupont de Nemours & Company disclaims all warranties with regard
to this software, including all implied warranties of merchantability
and fitness, in no event shall E. I. Dupont de Nemours & Company be
liable for any special, indirect or consequential damages or any
damages whatsoever resulting from loss of use, data or profits, whether
in an action of contract, negligence or other tortious action, arising
out of or in connection with the use or performance of this software.
.SH AUTHORS
John Cristy, E.I. DuPont De Nemours & Company Incorporated
X
SHAR_EOF
chmod 0755 ImageMagick/import.man ||
echo 'restore of ImageMagick/import.man failed'
Wc_c="`wc -c < 'ImageMagick/import.man'`"
test 3992 -eq "$Wc_c" ||
echo 'ImageMagick/import.man: original size 3992, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/kolb.c ==============
if test -f 'ImageMagick/kolb.c' -a X"$1" != X"-c"; then
echo 'x - skipping ImageMagick/kolb.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/kolb.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/kolb.c' &&
/*
X March 1990
X
X This is essentially Craig Kolb's color reduction code. I made a few
X changes mostly in routine colorquant (which now called Quantize) to
X support my MIFF image format. This version also allows 4096 colors
X instead of 256.
X
X cristy at dupont.com
*/
X
static void QuantHistogram();
static void BoxStats();
static void UpdateFrequencies();
static void ComputeRGBMap();
static void SetRGBmap();
static void find_colors();
static int CutBoxes();
static int CutBox();
static int GreatestVariance();
static int FindCutpoint();
static int getneighbors();
static int makenearest();
X
/*
X * This software is copyrighted as noted below. It may be freely copied,
X * modified, and redistributed, provided that the copyright notice is
X * preserved on all copies.
X *
X * There is no warranty or other guarantee of fitness for this software,
X * it is provided solely "as is". Bug reports or fixes may be sent
X * to the author, who may or may not act on them as he desires.
X *
X * You may not include this software in a program or other software product
X * without supplying the source, or without informing the end-user that the
X * source is available for no extra charge.
X *
X * If you modify this software, you should include a notice giving the
X * name of the person performing the modification, the date of modification,
X * and the reason for such modification.
X */
/*
X * colorquant.c
X *
X * Perform variance-based color quantization on a "full color" image.
X * Author: Craig Kolb
X * Department of Mathematics
X * Yale University
X * kolb at yale.edu
X * Date: Tue Aug 22 1989
X * Copyright (C) 1989 Craig E. Kolb
X * $Id: colorquant.c,v 1.3 89/12/03 18:27:16 craig Exp $
X *
X * $Log: colorquant.c,v $
X * Revision 1.3 89/12/03 18:27:16 craig
X * Removed bogus integer casts in distance calculation in makenearest().
X *
X * Revision 1.2 89/12/03 18:13:12 craig
X * FindCutpoint now returns FALSE if the given box cannot be cut. This
X * to avoid overflow problems in CutBox.
X * "whichbox" in GreatestVariance() is now initialized to 0.
X *
X */
#include "display.h"
#include "image.h"
#ifndef HUGE
#define HUGE HUGE_VAL
#endif
/*
X * Maximum number of colormap entries. To make larger than 2^8, the rgbmap
X * type will have to be changed from unsigned chars to something larger.
X */
#define MAXCOLORS 255
/*
X * Value corresponding to full intensity in colormap. The values placed
X * in the colormap are scaled to be between zero and this number. Note
X * that anything larger than 255 is going to lead to problems, as the
X * colormap is declared as an unsigned char.
X */
#define FULLINTENSITY 255
#define MAX(x,y) ((x) > (y) ? (x) : (y))
X
/*
X * Readability constants.
X */
#define REDI 0
#define GREENI 1
#define BLUEI 2
#define TRUE 1
#define FALSE 0
X
typedef struct {
X double
X weightedvar; /* weighted variance */
X
X float
X mean[3]; /* centroid */
X
X unsigned long
X weight, /* # of pixels in box */
X freq[3][MAXCOLORS]; /* Projected frequencies */
X
X int
X low[3],
X high[3]; /* Box extent */
} Box;
X
unsigned long
X *Histogram, /* image histogram */
X NPixels; /* total # of pixels */
X
unsigned int
X Colors, /* Maximum colormap entries */
X Bits, /* # significant input bits */
X ColormaxI; /* # of colors, 2^Bits */
X
/*
X * Perform variance-based color quantization on a 24-bit image.
X *
X * Input consists of:
X * red, green, blue Arrays of red, green and blue pixel
X * intensities stored as unsigned characters.
X * The color of the ith pixel is given
X * by red[i] green[i] and blue[i]. 0 indicates
X * zero intensity, 255 full intensity.
X * pixels The length of the red, green and blue arrays
X * in bytes, stored as an unsigned long int.
X * colormap Points to the colormap. The colormap
X * consists of red, green and blue arrays.
X * The red/green/blue values of the ith
X * colormap entry are given respectively by
X * colormap[0][i], colormap[1][i] and
X * colormap[2][i]. Each entry is an unsigned char.
X * colors The number of colormap entries, stored
X * as an integer.
X * bits The number of significant bits in each entry
X * of the red, green and blue arrays. An integer.
X * rgbmap An array of unsigned chars of size (2^bits)^3.
X * This array is used to map from pixels to
X * colormap entries. The 'prequantized' red,
X * green and blue components of a pixel
X * are used as an index into rgbmap to retrieve
X * the index which should be used into the colormap
X * to represent the pixel. In short:
X * index = rgbmap[(((r << bits) | g) << bits) | b];
X * fast If non-zero, the rgbmap will be constructed
X * quickly. If zero, the rgbmap will be built
X * much slower, but more accurately. In most
X * cases, fast should be non-zero, as the error
X * introduced by the approximation is usually
X * small. 'Fast' is stored as an integer.
X *
X * colorquant returns the number of colors to which the image was
X * quantized.
X */
X
/*
X March 1990
X
X This routine was radically changed from Craig colorquant routine to
X support my MIFF image format.
X
X cristy at dupont.com
*/
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% Q u a n t i z e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Function Quantize takes a 24 bit image and reduces the number of colors
% so it can be displayed on raster device with less bits per pixel. In most
% instances, the quantized image closely resembles the original reference
% image.
%
% The format of the Quantize routine is:
%
% colors=Quantize(image,number_colors,tree_depth,dither,optimal)
%
% A description of each parameter follows.
%
% o colors: The Quantize function returns this integer
% value. It is the actual number of colors allocated in the
% colormap. Note, the actual number of colors allocated may be less
% than the number of colors requested, but never more.
%
% o image: Specifies a pointer to an Image structure; returned from
% ReadImage.
%
% o number_colors: This integer value indicates the maximum number of
% colors in the quantized image or colormap. The actual number of
% colors allocated to the colormap may be less than this value, but
% never more. Note, the number of colors is restricted to a value
% less than or equal to 65536 if the continuous_tone parameter has a
% value of zero.
%
% o tree_depth: Normally, this integer value is zero or one. A zero or
% one tells Quantize to choose a optimal tree depth of Log4(number_colors).
% A tree of this depth generally allows the best representation of the
% reference image with the least amount of memory and the fastest
% computational speed. In some cases, such as an image with low color
% dispersion (a few number of colors), a value other than
% Log4(number_colors) is required. To expand the color tree completely,
% use a value of 8.
%
% o dither: Set this integer value to something other than zero to
% dither the quantized image. The basic strategy of dithering is to
% trade intensity resolution for spatial resolution by averaging the
% intensities of several neighboring pixels. Images which suffer
% from severe contouring when quantized can be improved with the
% technique of dithering. Severe contouring generally occurs when
% quantizing to very few colors, or to a poorly-chosen colormap.
% Note, dithering is a computationally expensive process and will
% increase processing time significantly.
%
% o optimal: An unsigned integer value greater than zero indicates that
% the optimal representation of the reference image should be returned.
%
%
*/
unsigned int Quantize(image,number_colors,tree_depth,dither,optimal)
Image
X *image;
X
unsigned int
X number_colors,
X tree_depth,
X dither,
X optimal;
{
X Box
X *Boxes; /* Array of color boxes. */
X
X extern unsigned int
X DitherImage();
X
X float
X Cfactor; /* Conversion factor */
X
X int
X i, /* Counter */
X OutColors, /* # of entries computed */
X Colormax; /* quantized full-intensity */
X
X register unsigned short
X index;
X
X RunlengthPacket
X *p;
X
X unsigned short
X *rgbmap;
X
X if (number_colors > MaxColormapSize)
X number_colors=MaxColormapSize;
X if (tree_depth > 1)
X tree_depth=Min(tree_depth,8);
X else
X if (number_colors > 1024)
X tree_depth=5;
X else
X tree_depth=6;
X ColormaxI = 1 << tree_depth; /* 2 ^ Bits */
X Colormax = ColormaxI - 1;
X Bits = tree_depth;
X NPixels = image->columns*image->rows;
X Cfactor = (float)FULLINTENSITY / Colormax;
X Histogram = (unsigned long *)
X calloc(ColormaxI*ColormaxI*ColormaxI,sizeof(long));
X rgbmap = (unsigned short *)
X calloc(ColormaxI*ColormaxI*ColormaxI,sizeof(unsigned short));
X Boxes = (Box *)malloc(number_colors * sizeof(Box));
X if ((Histogram == NULL) || (rgbmap == NULL) || (Boxes == NULL))
X {
X (void) fprintf(stderr,"Can't continue, not enough memory\n");
X exit(1);
X }
X QuantHistogram(image, &Boxes[0]);
X OutColors = CutBoxes(Boxes, (int) number_colors);
X /*
X * We now know the set of representative colors. We now
X * must fill in the colormap and convert the representatives
X * from their 'prequantized' range to 0-FULLINTENSITY.
X */
X image->colors=OutColors;
X for (i = 0; i < image->colors; i++)
X {
X image->colormap[i].red=(unsigned char) (Boxes[i].mean[REDI]*Cfactor+0.5);
X image->colormap[i].green=(unsigned char)
X (Boxes[i].mean[GREENI]*Cfactor+0.5);
X image->colormap[i].blue=(unsigned char) (Boxes[i].mean[BLUEI]*Cfactor+0.5);
X }
X if (dither)
X dither=!DitherImage(image);
X if (!dither)
X {
X ComputeRGBMap(Boxes, OutColors, rgbmap, (int) tree_depth, !optimal);
X p=image->pixels;
X for (i=0; i < image->packets; i++)
X {
X index=(rgbmap[((((p->red >> (8-Bits))<<Bits) |
X (p->green >> (8-Bits)))<<Bits) | (p->blue >> (8-Bits))]);
X p->index=index;
X p++;
X }
X }
X free((char *)Histogram);
X free((char *)Boxes);
X free((char *)rgbmap);
X return((unsigned int) OutColors); /* Return # of colormap entries */
}
X
/*
X * Compute the histogram of the image as well as the projected frequency
X * arrays for the first world-encompassing box.
X */
static void QuantHistogram(image, box)
Image
X *image;
Box *box;
{
X unsigned long *rf, *gf, *bf, i;
X RunlengthPacket
X *p;
X
X rf = box->freq[0];
X gf = box->freq[1];
X bf = box->freq[2];
X
X /*
X * Zero-out the projected frequency arrays of the largest box.
X * We compute both the histogram and the proj. frequencies of
X * the first box at the same time to save a pass through the
X * entire image.
X */
X for (i=0; i < ColormaxI; i++)
X {
X rf[i]=0;
X gf[i]=0;
X bf[i]=0;
X }
X
X /*
X Modified to accept my runlength-encoded format.
X
X cristy at dupont.com
X */
X p=image->pixels;
X for (i = 0; i < image->packets; i++) {
X rf[p->red >> (8-Bits)]+=(p->length+1);
X gf[p->green >> (8-Bits)]+=(p->length+1);
X bf[p->blue >> (8-Bits)]+=(p->length+1);
X Histogram[((((p->red >> (8-Bits))<<Bits)|(p->green >> (8-Bits)))<<Bits)|
X (p->blue >> (8-Bits))]+=(p->length+1);
X p++;
X }
}
X
/*
X * Iteratively cut the boxes.
X */
static int CutBoxes(boxes, colors)
Box *boxes;
int colors;
{
X int curbox;
X
X boxes[0].low[REDI] = boxes[0].low[GREENI] = boxes[0].low[BLUEI] = 0;
X boxes[0].high[REDI] = boxes[0].high[GREENI] =
X boxes[0].high[BLUEI] = ColormaxI;
X boxes[0].weight = NPixels;
X
X BoxStats(&boxes[0]);
X
X for (curbox = 1; curbox < colors; curbox++) {
X if (CutBox(&boxes[GreatestVariance(boxes, curbox)],
X &boxes[curbox]) == FALSE)
X break;
X }
X return curbox;
}
X
/*
X * Return the number of the box in 'boxes' with the greatest variance.
X * Restrict the search to those boxes with indices between 0 and n-1.
X */
static int GreatestVariance(boxes, n)
Box *boxes;
int n;
{
X register int i, whichbox = 0;
X double max;
X
X max = -1;
X for (i = 0; i < n; i++) {
X if (boxes[i].weightedvar > max) {
X max = boxes[i].weightedvar;
X whichbox = i;
X }
X }
X return whichbox;
}
X
/*
X * Compute mean and weighted variance of the given box.
X */
static void BoxStats(box)
register Box *box;
{
X register int i, color;
X unsigned long *freq;
X float mean;
X double var;
X
X if(box->weight == 0) {
X box->weightedvar = 0;
X return;
X }
X
X box->weightedvar = 0.;
X for (color = 0; color < 3; color++) {
X var = mean = 0;
X i = box->low[color];
X freq = &box->freq[color][i];
X for (; i < box->high[color]; i++, freq++) {
X mean += i * *freq;
X var += i*i* *freq;
X }
X box->mean[color] = mean / (float)box->weight;
X box->weightedvar += var - box->mean[color]*box->mean[color]*
X (float)box->weight;
X }
X box->weightedvar /= NPixels;
}
X
/*
X * Cut the given box. Returns TRUE if the box could be cut, FALSE otherwise.
X */
static int CutBox(box, newbox)
Box *box, *newbox;
{
X int i;
X double totalvar[3];
X Box newboxes[3][2];
X
X if (box->weightedvar == 0. || box->weight == 0)
X /*
X * Can't cut this box.
X */
X return FALSE;
X
X /*
X * Find 'optimal' cutpoint along each of the red, green and blue
X * axes. Sum the variances of the two boxes which would result
X * by making each cut and store the resultant boxes for
X * (possible) later use.
X */
X for (i = 0; i < 3; i++) {
X if (FindCutpoint(box, i, &newboxes[i][0], &newboxes[i][1]))
X totalvar[i] = newboxes[i][0].weightedvar +
X newboxes[i][1].weightedvar;
X else
X totalvar[i] = HUGE;
X }
X
X /*
X * Find which of the three cuts minimized the total variance
X * and make that the 'real' cut.
X */
X if (totalvar[REDI] <= totalvar[GREENI] &&
X totalvar[REDI] <= totalvar[BLUEI]) {
X *box = newboxes[REDI][0];
X *newbox = newboxes[REDI][1];
X } else if (totalvar[GREENI] <= totalvar[REDI] &&
X totalvar[GREENI] <= totalvar[BLUEI]) {
X *box = newboxes[GREENI][0];
X *newbox = newboxes[GREENI][1];
X } else {
X *box = newboxes[BLUEI][0];
X *newbox = newboxes[BLUEI][1];
X }
X
X return TRUE;
}
X
/*
X * Compute the 'optimal' cutpoint for the given box along the axis
X * indicated by 'color'. Store the boxes which result from the cut
X * in newbox1 and newbox2.
X */
static int FindCutpoint(box, color, newbox1, newbox2)
Box *box, *newbox1, *newbox2;
int color;
{
X float u, v, max;
X int i, maxindex, minindex, cutpoint;
X unsigned long optweight, curweight;
X
X if (box->low[color] + 1 == box->high[color])
X return FALSE; /* Cannot be cut. */
X minindex = (int)((box->low[color] + box->mean[color]) * 0.5);
X maxindex = (int)((box->mean[color] + box->high[color]) * 0.5);
X
X cutpoint = minindex;
X optweight = box->weight;
X
X curweight = 0.;
X for (i = box->low[color] ; i < minindex ; i++)
X curweight += box->freq[color][i];
X u = 0.;
X max = -1;
X for (i = minindex; i <= maxindex ; i++) {
X curweight += box->freq[color][i];
X if (curweight == box->weight)
X break;
X u += (float)(i * box->freq[color][i]) /
X (float)box->weight;
X v = ((float)curweight / (float)(box->weight-curweight)) *
X (box->mean[color]-u)*(box->mean[color]-u);
X if (v > max) {
X max = v;
X cutpoint = i;
X optweight = curweight;
X }
X }
X cutpoint++;
X *newbox1 = *newbox2 = *box;
X newbox1->weight = optweight;
X newbox2->weight -= optweight;
X newbox1->high[color] = cutpoint;
X newbox2->low[color] = cutpoint;
X UpdateFrequencies(newbox1, newbox2);
X BoxStats(newbox1);
X BoxStats(newbox2);
X
X return TRUE; /* Found cutpoint. */
}
X
/*
X * Update projected frequency arrays for two boxes which used to be
X * a single box.
X */
static void UpdateFrequencies(box1, box2)
register Box *box1, *box2;
{
X register unsigned long myfreq, *h;
X register int b, g, i, r;
X int roff;
X
X for (i=0; i < ColormaxI; i++)
X {
X box1->freq[0][i]=0;
X box1->freq[1][i]=0;
X box1->freq[2][i]=0;
X }
X
X for (r = box1->low[0]; r < box1->high[0]; r++) {
X roff = r << Bits;
X for (g = box1->low[1];g < box1->high[1]; g++) {
X b = box1->low[2];
X h = Histogram + (((roff | g) << Bits) | b);
X for (; b < box1->high[2]; b++) {
X if ((myfreq = *h++) == 0)
X continue;
X box1->freq[0][r] += myfreq;
X box1->freq[1][g] += myfreq;
X box1->freq[2][b] += myfreq;
X box2->freq[0][r] -= myfreq;
X box2->freq[1][g] -= myfreq;
X box2->freq[2][b] -= myfreq;
X }
X }
X }
}
X
/*
X * Compute RGB to colormap index map.
X */
static void ComputeRGBMap(boxes, colors, rgbmap, bits, fast)
Box *boxes;
int colors;
unsigned short *rgbmap ;
int bits, fast;
{
X register int i;
X
X if (fast) {
X /*
X * The centroid of each box serves as the representative
X * for each color in the box.
X */
X for (i = 0; i < colors; i++)
X SetRGBmap(i, &boxes[i], rgbmap, bits);
X } else
X /*
X * Find the 'nearest' representative for each
X * pixel.
X */
X find_colors(boxes, colors, rgbmap, bits);
}
X
/*
X * Make the centroid of "boxnum" serve as the representative for
X * each color in the box.
X */
static void SetRGBmap(boxnum, box, rgbmap, bits)
int boxnum;
Box *box;
unsigned short *rgbmap;
int bits;
{
X register int r, g, b;
X
X for (r = box->low[REDI]; r < box->high[REDI]; r++) {
X for (g = box->low[GREENI]; g < box->high[GREENI]; g++) {
X for (b = box->low[BLUEI]; b < box->high[BLUEI]; b++) {
X rgbmap[(((r<<bits)|g)<<bits)|b]=(unsigned short)boxnum;
X }
X }
X }
}
/*
X * Form colormap and NearestColor arrays.
X */
static void find_colors(boxes, colors, rgbmap, bits)
int colors;
Box *boxes;
unsigned short *rgbmap;
int bits;
{
X register int i;
X int num, *neighbors;
X
X neighbors = (int *)malloc((unsigned int) colors * sizeof(int));
X
X /*
X * Form map of representative (nearest) colors.
X */
X for (i = 0; i < colors; i++) {
X /*
X * Create list of candidate neighbors and
X * find closest representative for each
X * color in the box.
X */
X num = getneighbors(boxes, i, neighbors, colors);
X makenearest(boxes, i, num, neighbors, rgbmap, bits);
X }
X free((char *)neighbors);
}
X
/*
X * In order to minimize our search for 'best representative', we form the
X * 'neighbors' array. This array contains the number of the boxes whose
X * centroids *might* be used as a representative for some color in the
X * current box. We need only consider those boxes whose centroids are closer
X * to one or more of the current box's corners than is the centroid of the
X * current box. 'Closeness' is measured by Euclidean distance.
X */
static int getneighbors(boxes, num, neighbors, colors)
Box *boxes;
int num, colors, *neighbors;
{
X register int i, j;
X Box *bp;
X float dist, LowR, LowG, LowB, HighR, HighG, HighB, ldiff, hdiff;
X
X bp = &boxes[num];
X
X ldiff = bp->low[REDI] - bp->mean[REDI];
X ldiff *= ldiff;
X hdiff = bp->high[REDI] - bp->mean[REDI];
X hdiff *= hdiff;
X dist = MAX(ldiff, hdiff);
X
X ldiff = bp->low[GREENI] - bp->mean[GREENI];
X ldiff *= ldiff;
X hdiff = bp->high[GREENI] - bp->mean[GREENI];
X hdiff *= hdiff;
X dist += MAX(ldiff, hdiff);
X
X ldiff = bp->low[BLUEI] - bp->mean[BLUEI];
X ldiff *= ldiff;
X hdiff = bp->high[BLUEI] - bp->mean[BLUEI];
X hdiff *= hdiff;
X dist += MAX(ldiff, hdiff);
X
#ifdef IRIS
X dist = fsqrt(dist);
#else
X dist = (float)sqrt((double)dist);
#endif
X
X /*
X * Loop over all colors in the colormap, the ith entry of which
X * corresponds to the ith box.
X *
X * If the centroid of a box is as close to any corner of the
X * current box as is the centroid of the current box, add that
X * box to the list of "neighbors" of the current box.
X */
X HighR = (float)bp->high[REDI] + dist;
X HighG = (float)bp->high[GREENI] + dist;
X HighB = (float)bp->high[BLUEI] + dist;
X LowR = (float)bp->low[REDI] - dist;
X LowG = (float)bp->low[GREENI] - dist;
X LowB = (float)bp->low[BLUEI] - dist;
X for (i = j = 0, bp = boxes; i < colors; i++, bp++) {
X if (LowR <= bp->mean[REDI] && HighR >= bp->mean[REDI] &&
X LowG <= bp->mean[GREENI] && HighG >= bp->mean[GREENI] &&
X LowB <= bp->mean[BLUEI] && HighB >= bp->mean[BLUEI])
X neighbors[j++] = i;
X }
X
X return j; /* Return the number of neighbors found. */
}
X
/*
X * Assign representative colors to every pixel in a given box through
X * the construction of the NearestColor array. For each color in the
X * given box, we look at the list of neighbors passed to find the
X * one whose centroid is closest to the current color.
X */
static int makenearest(boxes, boxnum, nneighbors, neighbors, rgbmap, bits)
Box *boxes;
int boxnum;
int nneighbors, *neighbors, bits;
unsigned short *rgbmap;
{
X register int n, b, g, r;
X double rdist, gdist, bdist, dist, mindist,total_dist;
X int which, *np;
X Box *box;
X extern unsigned long *Histogram;
X
X box = &boxes[boxnum];
X
X for (r = box->low[REDI]; r < box->high[REDI]; r++) {
X for (g = box->low[GREENI]; g < box->high[GREENI]; g++) {
X for (b = box->low[BLUEI]; b < box->high[BLUEI]; b++) {
/*
X * The following two lines should be commented out if the RGBmap is going
X * to be used for images other than the one given.
X */
X if (Histogram[(((r<<bits)|g)<<bits)|b] == 0)
X continue;
X mindist = HUGE;
X /*
X * Find the colormap entry which is
X * closest to the current color.
X */
X np = neighbors;
X for (n = 0; n < nneighbors; n++, np++) {
X rdist = r-boxes[*np].mean[REDI];
X gdist = g-boxes[*np].mean[GREENI];
X dist = rdist*rdist;
X total_dist = dist + gdist*gdist;
X if (total_dist < dist)
X continue;
X bdist = b-boxes[*np].mean[BLUEI];
X dist = total_dist + bdist*bdist;
X if (dist >= total_dist)
X if (dist < mindist) {
X mindist = dist;
X which = *np;
X }
X }
X /*
X * The colormap entry closest to this
X * color is used as a representative.
X */
X rgbmap[(((r<<bits)|g)<<bits)|b] = (unsigned short) which;
X }
X }
X }
}
SHAR_EOF
chmod 0755 ImageMagick/kolb.c ||
echo 'restore of ImageMagick/kolb.c failed'
Wc_c="`wc -c < 'ImageMagick/kolb.c'`"
test 22830 -eq "$Wc_c" ||
echo 'ImageMagick/kolb.c: original size 22830, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/quantize.c ==============
if test -f 'ImageMagick/quantize.c' -a X"$1" != X"-c"; then
echo 'x - skipping ImageMagick/quantize.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/quantize.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/quantize.c' &&
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% QQQ U U AAA N N TTTTT IIIII ZZZZZ EEEEE %
% Q Q U U A A NN N T I ZZ E %
% Q Q U U AAAAA N N N T I ZZZ EEEEE %
% Q QQ U U A A N NN T I ZZ E %
% QQQQ UUU A A N N T IIIII ZZZZZ EEEEE %
% %
% %
% Quantize a Color Image %
% %
% %
% %
% Software Design %
% John Cristy %
% October 1990 %
% %
% %
% Copyright 1990 E. I. Dupont de Nemours & Company %
% %
% Permission to copy, modify, distribute, or sell this software or its %
% documentation for any purpose is hereby denied without specific, written %
% prior permission from E. I. Dupont de Nemours & Company. %
% %
% E. I. Dupont de Nemours & Company disclaims all warranties with regard %
% to this software, including all implied warranties of merchantability %
% and fitness, in no event shall E. I. Dupont de Nemours & Company be %
% liable for any special, indirect or consequential damages or any %
% damages whatsoever resulting from loss of use, data or profits, whether %
% in an action of contract, negligence or other tortious action, arising %
% out of or in connection with the use or performance of this software. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Realism in computer graphics typically requires using 24 bits/pixel to
% generate an image. Yet many graphic display devices do not contain
% the amount of memory necessary to match the spatial and color
% resolution of the human eye. The QUANTIZE program takes a 24 bit
% image and reduces the number of colors so it can be displayed on
% raster device with less bits per pixel. In most instances, the
% quantized image closely resembles the original reference image.
%
% A reduction of colors in an image is also desirable for image
% transmission and real-time animation.
%
% Function Quantize takes a standard RGB or monochrome images and quantizes
% them down to some fixed number of colors.
%
%
*/
X
/*
X Include declarations.
*/
#include "display.h"
#include "image.h"
X
unsigned int
X squares[MaxRgb+MaxRgb+1];
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% C l o s e s t C o l o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Function ClosestColor traverses the color cube tree at a particular node
% and determines which colormap entry best represents the input color.
%
% The format of the ClosestColor routine is:
%
% ClosestColor(node)
%
% A description of each parameter follows.
%
% o node: The address of a structure of type Node which points to a
% node in the color cube tree that is to be pruned.
%
%
*/
static int ClosestColor(image,red,green,blue)
Image
X *image;
X
register unsigned char
X red,
X green,
X blue;
{
X register ColorPacket
X *p;
X
X register int
X i;
X
X register int
X color_number;
X
X unsigned long
X blue_distance,
X distance,
X green_distance,
X minimum_distance,
X red_distance;
X
X p=image->colormap;
X minimum_distance=(~0);
X for (i=0; i < image->colors; i++)
X {
X red_distance=red-p->red+MaxRgb;
X green_distance=green-p->green+MaxRgb;
X blue_distance=blue-p->blue+MaxRgb;
X distance=squares[red_distance]+squares[green_distance]+
X squares[blue_distance];
X if (distance < minimum_distance)
X {
X minimum_distance=distance;
X color_number=i;
X if (distance == 0)
X break;
X }
X p++;
X }
X return(color_number);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% D i t h e r I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Procedure DitherImage uses the Floyd-Steinberg algorithm to dither the
% image. Refer to "An Adaptive Algorithm for Spatial GreySscale", Robert W.
% Floyd and Louis Steinberg, Proceedings of the S.I.D., Volume 17(2), 1976.
%
% First find the closest representation to the reference pixel color in the
% colormap, the node pixel is assigned this color. Next, the colormap color
% is subtracted from the reference pixels color, this represents the
% quantization error. Various amounts of this error are added to the pixels
% ahead and below the node pixel to correct for this error. The error
% proportions are:
%
% P 7/16
% 3/16 5/16 1/16
%
% The error is distributed left-to-right for even scanlines and right-to-left
% for odd scanlines.
%
% The format of the DitherImage routine is:
%
% DitherImage(image)
%
% A description of each parameter follows.
%
% o image: Specifies a pointer to an Image structure; returned from
% ReadImage.
%
%
*/
unsigned int DitherImage(image)
Image
X *image;
{
X typedef struct _ScaledColorPacket
X {
X long int
X red,
X green,
X blue;
X } ScaledColorPacket;
X
X ColorPacket
X *dithered_pixels;
X
X int
X *cache,
X j;
X
X register ColorPacket
X *q;
X
X register ScaledColorPacket
X *cs,
X *ns;
X
X register int
X blue_error,
X green_error,
X red_error,
X step;
X
X register RunlengthPacket
X *p;
X
X ScaledColorPacket
X *scanline;
X
X unsigned int
X i,
X x,
X y;
X
X for (j=(-MaxRgb); j <= MaxRgb; j++)
X squares[j+MaxRgb]=j*j;
X /*
X Allocate the cache & scanline buffers to keep track of quantization error.
X */
X dithered_pixels=(ColorPacket *)
X malloc(image->columns*image->rows*sizeof(ColorPacket));
X cache=(int *) malloc((1 << 18)*sizeof(int));
X scanline=(ScaledColorPacket *)
X malloc(2*(image->columns+2)*sizeof(ScaledColorPacket));
X if ((dithered_pixels == (ColorPacket *) NULL) || (cache == (int *) NULL) ||
X (scanline == (ScaledColorPacket *) NULL))
X {
X Warning("unable to dither image","memory allocation failed");
X return(True);
X }
X /*
X Initialize cache buffer.
X */
X for (i=0; i < (1 << 18); i++)
X cache[i]=(-1);
X /*
X Preload first scanline.
X */
X p=image->pixels;
X image->runlength=p->length+1;
X cs=scanline+1;
X for (i=0; i < image->columns; i++)
X {
X if (image->runlength > 0)
X image->runlength--;
X else
X {
X p++;
X image->runlength=p->length;
X }
X cs->red=p->red << 14;
X cs->green=p->green << 14;
X cs->blue=p->blue << 14;
X cs++;
X }
X for (y=0; y < image->rows; y++)
X {
X /*
X Read another scanline.
X */
X ns=scanline+(image->columns+2)*((y+1) % 2)+1;
X if (y < (image->rows-1))
X for (i=0; i < image->columns; i++)
X {
X if (image->runlength > 0)
X image->runlength--;
X else
X {
X p++;
X image->runlength=p->length;
X }
X ns->red=p->red << 14;
X ns->green=p->green << 14;
X ns->blue=p->blue << 14;
X ns++;
X }
X /*
X Distribute error left-to-right for even scanlines and right-to-left for
X odd scanlines.
X */
X q=dithered_pixels+image->columns*y+(y % 2 ? image->columns-1 : 0);
X cs=scanline+((y+0) % 2 ? image->columns+2 : 0)+
X (y % 2 ? image->columns-1 : 0)+1;
X ns=scanline+((y+1) % 2 ? image->columns+2 : 0)+
X (y % 2 ? image->columns-1 : 0)+1;
X step=(y % 2 ? -1 : 1);
X for (x=0; x < image->columns; x++)
X {
X if (cs->red < 0)
X red_error=0;
X else
X if (cs->red > (MaxRgb << 14))
X red_error=MaxRgb << 14;
X else
X red_error=cs->red;
X if (cs->green < 0)
X green_error=0;
X else
X if (cs->green > (MaxRgb << 14))
X green_error=MaxRgb << 14;
X else
X green_error=cs->green;
X if (cs->blue < 0)
X blue_error=0;
X else
X if (cs->blue > (MaxRgb << 14))
X blue_error=MaxRgb << 14;
X else
X blue_error=cs->blue;
X q->red=(red_error+(1 << 13)-1) >> 14;
X q->green=(green_error+(1 << 13)-1) >> 14;
X q->blue=(blue_error+(1 << 13)-1) >> 14;
X i=(q->red >> 2) << 12 | (q->green >> 2) << 6 | q->blue >> 2;
X if (cache[i] < 0)
X cache[i]=ClosestColor(image,q->red,q->green,q->blue);
X q->index=(unsigned short) cache[i];
X red_error-=image->colormap[q->index].red << 14;
X green_error-=image->colormap[q->index].green << 14;
X blue_error-=image->colormap[q->index].blue << 14;
X q+=step;
X /*
X Propagate the error in these proportions:
X Q 7/16
X 3/16 5/16 1/16
X */
X cs+=step;
X cs->red+=red_error*7 >> 4;
X cs->green+=green_error*7 >> 4;
X cs->blue+=blue_error*7 >> 4;
X ns-=step;
X ns->red+=red_error*3 >> 4;
X ns->green+=green_error*3 >> 4;
X ns->blue+=blue_error*3 >> 4;
X ns+=step;
X ns->red+=red_error*5 >> 4;
X ns->green+=green_error*5 >> 4;
X ns->blue+=blue_error*5 >> 4;
X ns+=step;
X ns->red+=(red_error-(red_error*15 >> 4));
X ns->green+=(green_error-(green_error*15 >> 4));
X ns->blue+=(blue_error-(blue_error*15 >> 4));
X }
X }
X (void) free((char *) scanline);
X (void) free((char *) cache);
X /*
X Convert dithered image to runlength-encoded pixels.
X */
X image->pixels=(RunlengthPacket *) realloc((char *)
X image->pixels,image->columns*image->rows*sizeof(RunlengthPacket));
X if (image->pixels == (RunlengthPacket *) NULL)
X {
X Warning("unable to dither image","memory allocation failed");
X return(True);
X }
X q=dithered_pixels;
X image->packets=0;
X p=image->pixels;
X p->length=MaxRunlength;
X for (i=0; i < (image->columns*image->rows); i++)
X {
X if ((q->red == p->red) && (q->green == p->green) &&
X (q->blue == p->blue) && (p->length < MaxRunlength))
X p->length++;
X else
X {
X if (image->packets > 0)
X p++;
X image->packets++;
X p->red=q->red;
X p->green=q->green;
X p->blue=q->blue;
X p->index=q->index;
X p->length=0;
X }
X q++;
X }
X (void) free((char *) dithered_pixels);
X image->pixels=(RunlengthPacket *)
X realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket));
X return(False);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% Q u a n t i z a t i o n E r r o r %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Function QuantizationError measures the difference between the original
% and quantized images. This difference is the total quantization error.
% The error is computed by summing over all pixels in an image the distance
% squared in RGB space between each reference pixel value and its quantized
% value.
%
% The format of the QuantizationError routine is:
%
% QuantizationError(image,mean_error_per_pixel,
% normalized_mean_square_error,normalized_maximum_square_error)
%
% A description of each parameter follows.
%
% o image: The address of a byte (8 bits) array of run-length
% encoded pixel data of your reference image. The sum of the
% run-length counts in the reference image must be equal to or exceed
% the number of pixels.
%
% o mean_error_per_pixel: The address of an integer value. The value
% returned is the mean error for any single pixel in the image.
%
% o normalized_mean_square_error: The address of a real value. The value
% returned is the normalized mean quantization error for any single
% pixel in the image. This distance measure is normalized to a
% range between 0 and 1. It is independent of the range of red,
% green, and blue values in your image.
%
% o normalized_maximum_square_error: The address of a real value. The value
% returned is the normalized maximum quantization error for any
% single pixel in the image. This distance measure is normalized to
% a range between 0 and 1. It is independent of the range of red,
% green, and blue values in your image.
%
%
*/
void QuantizationError(image,mean_error_per_pixel,normalized_mean_square_error,
X normalized_maximum_square_error)
Image
X *image;
X
unsigned int
X *mean_error_per_pixel;
X
double
X *normalized_mean_square_error,
X *normalized_maximum_square_error;
{
X register int
X i;
X
X register RunlengthPacket
X *p;
X
X register unsigned long
X blue_distance,
X green_distance,
X red_distance;
X
X unsigned long
X distance,
X maximum_error_per_pixel,
X total_error;
X
X /*
X For each pixel, collect error statistics.
X */
X for (i=(-MaxRgb); i <= MaxRgb; i++)
X squares[i+MaxRgb]=i*i;
X maximum_error_per_pixel=0;
X total_error=0;
X p=image->pixels;
X for (i=0; i < image->packets; i++)
X {
X red_distance=p->red-image->colormap[p->index].red+MaxRgb;
X green_distance=p->green-image->colormap[p->index].green+MaxRgb;
X blue_distance=p->blue-image->colormap[p->index].blue+MaxRgb;
X distance=squares[red_distance]+squares[green_distance]+
X squares[blue_distance];
X total_error+=(distance*(p->length+1));
X if (distance > maximum_error_per_pixel)
X maximum_error_per_pixel=distance;
X p++;
X }
X /*
X Compute final error statistics.
X */
X *mean_error_per_pixel=total_error/(image->columns*image->rows);
X *normalized_mean_square_error=((double) *mean_error_per_pixel)/
X (3.0*MaxRgb*MaxRgb);
X *normalized_maximum_square_error=((double) maximum_error_per_pixel)/
X (3.0*MaxRgb*MaxRgb);
}
X
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% Q u a n t i z e I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% QuantizeImage analyzes the colors within a reference image and chooses a
% fixed number of colors to represent the image. The goal of the algorithm
% is to minimize the difference between the input and output image while
% minimizing the processing time.
%
% The format of the QuantizeImage routine is:
%
% QuantizeImage(image,number_colors,tree_depth,dither,optimal)
%
% A description of each parameter follows:
%
% o image: Specifies a pointer to an Image structure; returned from
% ReadImage.
%
% o number_colors: This integer value indicates the maximum number of
% colors in the quantized image or colormap. The actual number of colors
% allocated to the colormap may be less than this value, but never more.
% Note, the number of colors is restricted to a value less than or equal
% to 65536 if the quantized image is not DirectClass.
%
% o tree_depth: Normally, this integer value is zero or one. A zero or
% one tells QUANTIZE to choose a optimal tree depth. An optimal depth
% generally allows the best representation of the reference image with the
% fastest computational speed and the least amount of memory. However,
% the default depth is inappropriate for some images. To assure the best
% representation, try values between 2 and 8 for this parameter.
%
% o dither: Set this integer value to something other than zero to
% dither the quantized image. The basic strategy of dithering is to
% trade intensity resolution for spatial resolution by averaging the
% intensities of several neighboring pixels. Images which suffer
% from severe contouring when quantized can be improved with the
% technique of dithering. Severe contouring generally occurs when
% quantizing to very few colors, or to a poorly-chosen colormap.
% Note, dithering is a computationally expensive process and will
% increase processing time significantly.
%
% o optimal: An unsigned integer value greater than zero indicates that
% the optimal representation of the reference image should be returned.
%
%
*/
void QuantizeImage(image,number_colors,tree_depth,dither,optimal)
Image
X *image;
X
unsigned int
X number_colors,
X tree_depth,
X dither,
X optimal;
{
X extern unsigned int
X Quantize();
X
X /*
X Allocate quantized colormap.
X */
X if (number_colors > MaxColormapSize)
X number_colors=MaxColormapSize;
X if (image->colormap != (ColorPacket *) NULL)
X (void) free((char *) image->colormap);
X image->colormap=(ColorPacket *) malloc(number_colors*sizeof(ColorPacket));
X if (image->colormap == (ColorPacket *) NULL)
X {
X Warning("unable to quantize image","memory allocation failed");
X exit(1);
X }
X /*
X Reduce the number of colors in the continuous tone image.
X */
X image->colors=Quantize(image,number_colors,tree_depth,dither,optimal);
X image->class=PseudoClass;
}
SHAR_EOF
chmod 0755 ImageMagick/quantize.c ||
echo 'restore of ImageMagick/quantize.c failed'
Wc_c="`wc -c < 'ImageMagick/quantize.c'`"
test 20010 -eq "$Wc_c" ||
echo 'ImageMagick/quantize.c: original size 20010, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= ImageMagick/rotate.c ==============
if test -f 'ImageMagick/rotate.c' -a X"$1" != X"-c"; then
echo 'x - skipping ImageMagick/rotate.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting ImageMagick/rotate.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ImageMagick/rotate.c' &&
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
SHAR_EOF
true || echo 'restore of ImageMagick/rotate.c failed'
fi
echo 'End of ImageMagick part 10'
echo 'File ImageMagick/rotate.c is continued in part 11'
echo 11 > _shar_seq_.tmp
exit 0
--
Dan Heller
O'Reilly && Associates Z-Code Software Comp-sources-x:
Senior Writer President comp-sources-x at uunet.uu.net
argv at ora.com argv at zipcode.com
More information about the Comp.sources.x
mailing list