comp.lang.c++
http://groups.google.com/group/comp.lang.c++?hl=en
comp.lang.c++@googlegroups.com
Today's topics:
* C++ standards committee looking at adding Cairo to the C++ standard - 13
messages, 8 authors
http://groups.google.com/group/comp.lang.c++/t/0b3c6e40a26c7051?hl=en
* Overloaded template resolution - 2 messages, 2 authors
http://groups.google.com/group/comp.lang.c++/t/16d19f355b1d27b4?hl=en
* Decoding GIF file in C? [Source code here] - 4 messages, 4 authors
http://groups.google.com/group/comp.lang.c++/t/dec6ec0426c88c64?hl=en
* different rounding behavior with float and double - 7 messages, 6 authors
http://groups.google.com/group/comp.lang.c++/t/05d32024f4d7a3b9?hl=en
==============================================================================
TOPIC: C++ standards committee looking at adding Cairo to the C++ standard
http://groups.google.com/group/comp.lang.c++/t/0b3c6e40a26c7051?hl=en
==============================================================================
== 1 of 13 ==
Date: Tues, Jan 7 2014 5:48 pm
From: woodbrian77@gmail.com
On Tuesday, January 7, 2014 5:22:00 PM UTC-6, Mr Flibble wrote:
>
> My segmented_array container is not /better/ than deque it is just
> /different/; it has different performance and invalidation
> characteristics for certain operations compared with vector, deque *and*
> list.
>
Your container is more flexible in that the user can pick the
segment size. That's better.
Brian
Ebenezer Enterprises
http://webEbenezer.net
== 2 of 13 ==
Date: Tues, Jan 7 2014 11:07 pm
From: Wouter van Ooijen
> When something is announced as a �C++ course�, it is easier to
> teach what actually /is/ part of C++, because people expect this
> and also I myself deem this to be honest.
You can't explain C++ without examples. Examples are not part of the
standard, so why not take real-world examples from the use of a library.
I assume your course has homework or something similar? There are no
assignments in the C++ standard. So when you select/write the
assignemnets, make them do somthing simple but real. Graphics are not
the only choice, but not a bad one.
Wouter
== 3 of 13 ==
Date: Wed, Jan 8 2014 1:45 am
From: Öö Tiib
On Wednesday, 8 January 2014 00:31:00 UTC+2, woodb...@gmail.com wrote:
> On Tuesday, January 7, 2014 4:13:19 PM UTC-6, Stefan Ram wrote:
> >
> > In the C++ standard, we have containers, algorithms,
> > an input/output library, a regular expressions library,
> > and more. What is there outside the standard to which
> > these are clearly inferior?
>
> Rather than using map, I suggest one of these:
> http://www.boost.org/doc/libs/1_55_0/doc/html/intrusive.html
'boost::intrusive' does not contain 'map'. So if someone needs
a map then 'std::map' is clearly superior for her. If someone does
not need a map then sure, why she used 'std::map'?
Note that the original intention of starters of boost was to build
libraries suitable for incorporation into the C++ language standard.
They actually have been quite successful with that. You basically
bring example from work that is meant for proposing to standard.
The major beneficial difference of intrusive containers is that
exactly same object can be in several different containers at same
time.
The other difference is that user has to manage the lifetime of
objects. Lot of users I have met have difficulties of optimal
resource management (coming from garbage collections) so that
difference can not be labeled as clearly beneficial.
I have seen cases in practice where 'boost::intrusive::set' results
with 4 times faster than 'std::set' with default allocator. 'std::set'
can be also made to perform as well as 'boost::intrusive::set' by
using custom allocator so it still does not mean it is clearly
inferior.
== 4 of 13 ==
Date: Wed, Jan 8 2014 5:53 am
From: Jorgen Grahn
On Tue, 2014-01-07, Ian Collins wrote:
> Stefan Ram wrote:
>> Ian Collins <ian-news@hotmail.com> writes:
>>> That's correct. I can't see how adding something to the standard makes
>>> it easier to teach. Whether a widget is a std::widget or one from a
>>
>> ... non-standard ...
>>
>>> library, it is still a widget.
>>
>> When something is announced as a �C++ course�, it is easier to
>> teach what actually /is/ part of C++, because people expect this
>> and also I myself deem this to be honest.
>
> But you aren't teaching the library, you are using a part of it to
> illustrate a concept.
When I was a student, it was not uncommon to have exercises based on
some library or other ready-made code. It was usually written by the
teacher or someone at the staff, and explicitly crude and simple, not
enough for real-world use.
E.g. we got the parser and the virtual machine/interpreter for free
when we did the compiler course and were supposed to focus on code
generation. We got a nice little railroad simulator (graphical, with
bells and whistles) when doing the concurrency course. And so on.
/Jorgen
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
== 5 of 13 ==
Date: Wed, Jan 8 2014 7:40 pm
From: Ian Collins
Jorgen Grahn wrote:
> On Tue, 2014-01-07, Ian Collins wrote:
>>
>> In most of my projects, they are the documentation (and implementation)
>> step between the user stories and the code.
>
> I wonder if I would find them /useful/ as documentation too ... are
> any of these projects publicly available so I could take a look?
I'm afraid not.
I try to name my tests so they document the behaviour of the code. The
tests them selves act as both detailed descriptions and examples of how
to use the code. I think this is much easier to do well if the tests
are written first.
>> Unlike JavaDoc style
>> comments, they are always up to date!
>
> Yeah, well ... I don't understand what's so hard about keeping
> documentation up to date. I frequently see people let it slip, and I
> cannot figure out why. Incompetence?
Usually time pressure!
--
Ian Collins
== 6 of 13 ==
Date: Wed, Jan 8 2014 11:54 pm
From: Rui Maciel
Stefan Ram wrote:
> Ian Collins <ian-news@hotmail.com> writes:
>>Teach them how things are done in the real world: pick a library and use
>>it.
>
> What works in the real world does not always work in the
> classroom. First, it does not even always work in the real
> world (many software project fail, are cancelled, or overdue).
I never heard of any case of a project failing due to having adopted a GUI toolkit which wasn't
included in an international standard.
> Next, the classes are already much too short to teach most
> of what is in the standard C++, so they only teach a selection.
> Teaching a »picked library« means that there will be even
> less time to teach C++ proper. While some students might
> like this, others might be alienated by it.
I don't see how you get more teaching time by adding a component to the C++ standard.
Rui Maciel
== 7 of 13 ==
Date: Thurs, Jan 9 2014 12:06 am
From: Rui Maciel
Öö Tiib wrote:
> I do not understand. Are you saying that first impression is irrelevant?
How many people got their first impression from C++ by reading the unreleased draft of the ISO
standard currently in development? Because it appears that so far with regards to first
impressions the language has been doing great so far.
> My point was that C++ toolset leaves sad first impression as state of art.
If you believe that standardizing GUI toolkits has anything to do with state of the art then
your concept is not only outdated by a decade or two but it also ignores history.
> C++ standard is guideline for people writing C++ compilers and standard
> library implementations so it has everything to do with improving that
> toolset.
Surely you must be aware that it's possible to develop components for C++ without having them
included in an ISO standard.
Rui maciel
== 8 of 13 ==
Date: Thurs, Jan 9 2014 12:12 am
From: Rui Maciel
Stefan Ram wrote:
> Ian Collins <ian-news@hotmail.com> writes:
>>That's correct. I can't see how adding something to the standard makes
>>it easier to teach. Whether a widget is a std::widget or one from a
>
> ... non-standard ...
>
>>library, it is still a widget.
>
> When something is announced as a »C++ course«, it is easier to
> teach what actually /is/ part of C++, because people expect this
> and also I myself deem this to be honest.
Do you believe that programs and/or libraries written in C++ aren't C++?
Rui Maciel
== 9 of 13 ==
Date: Thurs, Jan 9 2014 3:14 am
From: Öö Tiib
On Thursday, 9 January 2014 10:06:43 UTC+2, Rui Maciel wrote:
> Öö Tiib wrote:
>
> > I do not understand. Are you saying that first impression is irrelevant?
>
> How many people got their first impression from C++ by reading the unreleased draft of the ISO
> standard currently in development? Because it appears that so far with regards to first
> impressions the language has been doing great so far.
I repeat ... I don't understand what you are saying. Explain?
A: First impression does not matter. (Then lets agree to disagreement.)
B: First impression that C++ leaves is good. (Then lets agree to disagreement.)
C: Graphics can't attract nor impress. (Then lets agree to disagreement.)
D: C++ standard can do nothing to improve C++. (Then lets agree to disagreement.)
E: ... <- Please fill it.
Where did I write that standard is meant for reading by students? I did specify
standard's audience and you quoted it below.
> > My point was that C++ toolset leaves sad first impression as state of art.
>
> If you believe that standardizing GUI toolkits has anything to do with state of the art then
> your concept is not only outdated by a decade or two but it also ignores history.
Unimpressive state of compilers, standard library and tools of C++ is direct result of C++
standard not requiring features that can attract or impress from those people who should
read it. Historic issues continue being issues until repaired, decades do not matter.
> > C++ standard is guideline for people writing C++ compilers and standard
> > library implementations so it has everything to do with improving that
> > toolset.
>
> Surely you must be aware that it's possible to develop components for C++ without having them
> included in an ISO standard.
My awareness does not help at all with issue that I described. IOW it is irrelevant.
Every third newbie question is:
"what is good C++ GUI toolkit?" (first two questions are about books and tutorials)
Every second answer to that question is:
"Qt is more or less OK, but it is LGPL and it is corporately owned and it switches owners
every two years and it creates large binaries and the code of it is not really C++ and it
does take some serious hacking to get it to work on iOS or Android ... and so on."
Is it impressive?
== 10 of 13 ==
Date: Thurs, Jan 9 2014 3:57 am
From: Rui Maciel
Rui Maciel wrote:
> I never heard of any case of a project failing due to having adopted a GUI
> toolkit which wasn't included in an international standard.
Correction: a basic 2D drawing API.
Rui Maciel
== 11 of 13 ==
Date: Thurs, Jan 9 2014 10:20 am
From: Jorgen Grahn
On Thu, 2014-01-09, Ian Collins wrote:
> Jorgen Grahn wrote:
>> On Tue, 2014-01-07, Ian Collins wrote:
>>>
>>> In most of my projects, they are the documentation (and implementation)
>>> step between the user stories and the code.
>>
>> I wonder if I would find them /useful/ as documentation too ... are
>> any of these projects publicly available so I could take a look?
>
> I'm afraid not.
Ah, too bad.
> I try to name my tests so they document the behaviour of the code. The
> tests them selves act as both detailed descriptions and examples of how
> to use the code. I think this is much easier to do well if the tests
> are written first.
I can imagine that working to some extent ... especially if you
clearly separate "illustrative" tests and "tricky edge cases" tests.
But I suspect personality is involved too. For example, I learn much
better by reading about principles than from examples.
>>> Unlike JavaDoc style
>>> comments, they are always up to date!
>>
>> Yeah, well ... I don't understand what's so hard about keeping
>> documentation up to date. I frequently see people let it slip, and I
>> cannot figure out why. Incompetence?
>
> Usually time pressure!
Not when the documentation is five lines up from the place they
change. Then they're virtually shouting "I didn't bother to learn
about the /intentions/ behind this code before I changed it"[1].
Fortunately it's quite easy to catch this in review.
/Jorgen
[1] Once again, assuming the documentation is relevant to begin
with. If it's not, I'm liable to forget too.
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
== 12 of 13 ==
Date: Thurs, Jan 9 2014 2:28 pm
From: "Chris M. Thomasson"
> "Rui Maciel" wrote in message news:labt7p$co4$1@dont-email.me...
> It appears that Herb Sutter wants to add a 2D drawing library to the C++
> standard, and he is
> looking at libCairo as a base for this library.
> The link to the Cairo's mailing list:
> http://lists.cairographics.org/archives/cairo/2013-December/024858.html
> What are your thoughts on this?
Graphics for C++, Humm. Perhaps raw bitmaps?
Then teach the students how to program their own line and circle
plotting algorithms in C++. Then go for Bezier Curves, and on and
on. Turning math into visual representations can be a powerful
method of teaching...
IMVHO, starting to learn 2d graphics from "scratch" is the essence
of the power of C++.
;^)
== 13 of 13 ==
Date: Thurs, Jan 9 2014 6:44 pm
From: "Alf P. Steinbach"
On 09.01.2014 23:28, Chris M. Thomasson wrote:
>> "Rui Maciel" wrote in message news:labt7p$co4$1@dont-email.me...
>
>> It appears that Herb Sutter wants to add a 2D drawing library to the
>> C++ standard, and he is
>> looking at libCairo as a base for this library.
>
>> The link to the Cairo's mailing list:
>> http://lists.cairographics.org/archives/cairo/2013-December/024858.html
>
>> What are your thoughts on this?
>
> Graphics for C++, Humm. Perhaps raw bitmaps?
>
> Then teach the students how to program their own line and circle
> plotting algorithms in C++. Then go for Bezier Curves, and on and
> on. Turning math into visual representations can be a powerful
> method of teaching...
>
> IMVHO, starting to learn 2d graphics from "scratch" is the essence
> of the power of C++.
>
> ;^)
http://www.boost.org/doc/libs/1_55_0/libs/gil/doc/index.html
cheers & hth.,
- Alf
==============================================================================
TOPIC: Overloaded template resolution
http://groups.google.com/group/comp.lang.c++/t/16d19f355b1d27b4?hl=en
==============================================================================
== 1 of 2 ==
Date: Mon, Jan 6 2014 8:01 pm
From: somenath
While going through the book C++ Primer (Third edition) I came across the following code from the book.
I have added the return statement and cout to trace the flow.
#include<iostream>
using namespace std;
template<class T>
T max(T t1, T t2) {
cout<<"Inside Template Fun"<<endl;
return t1;
}
//Two ordinary functions
char max(char c1,char c2)
{
cout<<"Inside char Fun "<<endl;
return c1;
}
double max(double d1, double d2 )
{
cout<<"Inside double Fun "<<endl;
return d1;
}
int main(void)
{
float fd;
max(0,fd);
return 0;
}
According to the book the compiler should be reporting error for the following reason.
"As the call (max(0,fd) ) is ambiguous ,only the ordinary functions are considered. Neither of these functions is selected as the best viable function, because the type conversions on the arguments are equally bad for both those functions: both arguments require standard conversion to match the corresponding parameter in either of the viable functions. The call is therefore ambiguous and is flagged as an error by the compiler."
But When I compile the above code in g++ I do not get any error and when I ran the program I get the following output.
"Inside double Fun"
According to me in max(0,fd); the first argument 0 is converted to double and fd is converted to double so the max(double d1, double d2 ) is getting called and as the promotion will not cause any loss of precision so it is fine therefore there is no ambiguity exists.
Is my understanding is correct? Am I wrongly interpreting author's point of view?
== 2 of 2 ==
Date: Wed, Jan 8 2014 1:51 am
From: Öö Tiib
On Tuesday, 7 January 2014 06:01:48 UTC+2, somenath wrote:
> While going through the book C++ Primer (Third edition) I came across
> the following code from the book.
Will you post it every day now? Yes, it is a defect in book. All books contain
defects and some examples do not even compile. It is anyway good book.
So contact the authors if you want them to fix the defect.
==============================================================================
TOPIC: Decoding GIF file in C? [Source code here]
http://groups.google.com/group/comp.lang.c++/t/dec6ec0426c88c64?hl=en
==============================================================================
== 1 of 4 ==
Date: Wed, Jan 8 2014 7:23 pm
From: kirannd1989@gmail.com
Hi..
i tried compiling this code but there are few undefined Macro/functions like MK_FP().
I am trying it on WIN32, VS2012.. i have made changes accordingly.
Is this solution dependent on any library.
Thanks in advance
On Monday, August 1, 1994 1:02:48 PM UTC+5:30, Cyborg wrote:
> In article <msm6.775622996@ra.msstate.edu> msm6@Ra.MsState.Edu (Muhammad Salman Mughal) writes:
> >
> >Hi there,
> >
> > I am desperately looking for a C code that could decode a GIF file
> > in DOS. Anybody out there who knows how to do it? I will really
> > appreciate any help.
> >
>
>
> The following code is based on a LZW decoder originally coded by Steven A.
> Bennett. All I did is write the code for parsing the GIF format, passing
> the approptiate data to the LZW decoder and writing the code for displaying
> the data on the screen. Both 87a and 89a formats are accepted.
>
> Video BIOS must support VESA functions - the code selects a video mode
> whith a resolution just high enough to display the given GIF file. Max
> resolution is 1280x1024, pictures larger than this will be partially
> displayed. Interlaced GIFs are supported. Program was only tested on my
> video card (Cirrus 5428 VESA Local Bus). It was not intended for public
> release but since I've already written it and the guy i desperate...
>
> Compiles with Borland C++ v3.1
>
> ----------------------- chop here --------------------------
>
> /* Various error codes used by decoder
> * and my own routines... It's okay
> * for you to define whatever you want,
> * as long as it's negative... It will be
> * returned intact up the various subroutine
> * levels...
> */
> #define READ_ERROR -1
> #define WRITE_ERROR -2
> #define OPEN_ERROR -3
> #define CREATE_ERROR -4
> #define OUT_OF_MEMORY -5
> #define BAD_CODE_SIZE -6
>
> #define ISIZE 2048 // image line size
> #define BSIZE 256 // buffer size
> #define PSIZE 768 // pallette size
> #define NULL 0L
> #define MAX_CODES 4095
>
> #include <dos.h>
> #include <conio.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> /* Static variables */
> short curr_size; /* The current code size */
> short clear; /* Value for a clear code */
> short ending; /* Value for a ending code */
> short newcodes; /* First available code */
> short top_slot; /* Highest code for current size */
> short slot; /* Last read code */
>
> /* The following static variables are used
> * for seperating out codes
> */
> short navail_bytes = 0; /* # bytes left in block */
> short nbits_left = 0; /* # bits left in current byte */
> unsigned char b1; /* Current byte */
> unsigned char byte_buff[257]; /* Current block */
> unsigned char *pbytes; /* Pointer to next byte in block */
>
> /* The reason we have these separated like this instead of using
> * a structure like the original Wilhite code did, is because this
> * stuff generally produces significantly faster code when compiled...
> * This code is full of similar speedups... (For a good book on writing
> * C for speed or for space optimisation, see Efficient C by Tom Plum,
> * published by Plum-Hall Associates...)
> */
> unsigned char stack[MAX_CODES + 1]; /* Stack for storing pixels */
> unsigned char suffix[MAX_CODES + 1]; /* Suffix table */
> unsigned short prefix[MAX_CODES + 1]; /* Prefix linked list */
>
> long code_mask[13] = {
> 0x0000,
> 0x0001, 0x0003, 0x0007, 0x000F,
> 0x001F, 0x003F, 0x007F, 0x00FF,
> 0x01FF, 0x03FF, 0x07FF, 0x0FFF
> };
>
> // incremented each time an out of range code is read by the decoder
> int bad_code_count;
>
> unsigned char far *buffer=NULL; // file buffer
> unsigned char far *grgb=NULL; // global rgb table
> unsigned char far *lrgb=NULL; // local rgb table
> unsigned char far *pixels=NULL; // line of pixels to be displayed
> unsigned char far *vid=NULL; // ptr to start of graphics window
> unsigned char background=0; // background color index
> unsigned long offset=0; // offset into graphics window
> unsigned long piclen; // total screen size in pixels
> unsigned int realx; // real picture width
> unsigned int realy; // real picture height
> unsigned int xsize=0; // graphic width
> unsigned int ysize=0; // graphic height
> unsigned int win=0; // window number
> unsigned int granularity=0; // granularity of video window
> unsigned int group=0; // picture group (interlaced or not)
> FILE *fp; // file pointer
>
> /* int get_byte()
> * - This function is expected to return the next byte from
> * the GIF file or a negative number defined in ERRS.H
> */
> int get_byte(){
> unsigned char c;
>
> if(fscanf(fp, "%c", &c)==1)
> return((int)c);
> else
> return(READ_ERROR);
> }
>
> /* int out_line(unsigned char pixels[], int linelen)
> * - This function takes a full line of pixels (one byte per pixel) and
> * displays them (or does whatever your program wants with them...). It
> * should return zero, or negative if an error or some other event occurs
> * which would require aborting the decode process... Note that the length
> * passed will almost always be equal to the line length passed to the
> * decoder function, with the sole exception occurring when an ending code
> * occurs in an odd place in the GIF file... In any case, linelen will be
> * equal to the number of pixels passed...
> */
> int out_line(unsigned char *pixels, int linelen){
> unsigned long segment;
>
> segment=offset&(unsigned long)(granularity-1);
>
> // put pixels on screen
> memmove(vid+segment, pixels, linelen);
> memset(vid+segment+linelen, background, xsize-linelen);
> switch (group) {
> case 0:
> offset+=xsize;
> break;
> case 1:
> offset+=xsize*8;
> if(offset>=piclen){
> group++;
> offset=xsize*4;
> }
> break;
> case 2:
> offset+=xsize*8;
> if(offset>=piclen){
> group++;
> offset=xsize*2;
> }
> break;
> case 3:
> offset+=xsize*4;
> if(offset>=piclen){
> group++;
> offset=xsize;
> }
> break;
> case 4:
> offset+=xsize*2;
> break;
> default:
> break;
> }
>
> // if we've run over a window granularity border, move window position
> if((offset>>12)!=win){
> win=offset>>12;
> asm pusha
> asm mov ax, 0x4f05
> asm mov bx, 0x0000
> asm mov dx, win
> asm int 0x10
> asm popa
> }
> return(1);
> }
>
>
> /* This function initializes the decoder for reading a new image.
> */
> static short init_exp(short size)
> {
> curr_size = size + 1;
> top_slot = 1 << curr_size;
> clear = 1 << size;
> ending = clear + 1;
> slot = newcodes = ending + 1;
> navail_bytes = nbits_left = 0;
> return(0);
> }
>
> /* get_next_code()
> * - gets the next code from the GIF file. Returns the code, or else
> * a negative number in case of file errors...
> */
> static short get_next_code()
> {
> short i, x;
> unsigned long ret;
>
> if (nbits_left == 0)
> {
> if (navail_bytes <= 0)
> {
>
> /* Out of bytes in current block, so read next block
> */
> pbytes = byte_buff;
> if ((navail_bytes = get_byte()) < 0)
> return(navail_bytes);
> else if (navail_bytes)
> {
> for (i = 0; i < navail_bytes; ++i)
> {
> if ((x = get_byte()) < 0)
> return(x);
> byte_buff[i] = x;
> }
> }
> }
> b1 = *pbytes++;
> nbits_left = 8;
> --navail_bytes;
> }
>
> ret = b1 >> (8 - nbits_left);
> while (curr_size > nbits_left)
> {
> if (navail_bytes <= 0)
> {
>
> /* Out of bytes in current block, so read next block
> */
> pbytes = byte_buff;
> if ((navail_bytes = get_byte()) < 0)
> return(navail_bytes);
> else if (navail_bytes)
> {
> for (i = 0; i < navail_bytes; ++i)
> {
> if ((x = get_byte()) < 0)
> return(x);
> byte_buff[i] = x;
> }
> }
> }
> b1 = *pbytes++;
> ret |= b1 << nbits_left;
> nbits_left += 8;
> --navail_bytes;
> }
> nbits_left -= curr_size;
> ret &= code_mask[curr_size];
> return((short)(ret));
> }
>
> /* DECODE.C - An LZW decoder for GIF
> *
> * Copyright (C) 1987, by Steven A. Bennett
> *
> * Permission is given by the author to freely redistribute and include
> * this code in any program as long as this credit is given where due.
> *
> * In accordance with the above, I want to credit Steve Wilhite who wrote
> * the code which this is heavily inspired by...
> *
> * GIF and 'Graphics Interchange Format' are trademarks (tm) of
> * Compuserve, Incorporated, an H&R Block Company.
> *
> * Release Notes: This file contains a decoder routine for GIF images
> * which is similar, structurally, to the original routine by Steve Wilhite.
> * It is, however, somewhat noticably faster in most cases.
> *
> * short decode(linewidth)
> * short linewidth; * Pixels per line of image *
> *
> * - This function decodes an LZW image, according to the method used
> * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
> * will generate a call to out_line(), which is a user specific function
> * to display a line of pixels. The function gets it's codes from
> * get_next_code() which is responsible for reading blocks of data and
> * seperating them into the proper size codes. Finally, get_byte() is
> * the global routine to read the next byte from the GIF file.
> *
> * It is generally a good idea to have linewidth correspond to the actual
> * width of a line (as specified in the Image header) to make your own
> * code a bit simpler, but it isn't absolutely necessary.
> *
> * Returns: 0 if successful, else negative. (See ERRS.H)
> *
> */
>
> short decode(short linewidth)
> {
> register unsigned char *sp, *bufptr;
> unsigned char *buf;
> register short code, fc, oc, bufcnt;
> short c, size, ret;
>
> /* Initialize for decoding a new image...
> */
> if ((size = get_byte()) < 0)
> return(size);
> if (size < 2 || 9 < size)
> return(BAD_CODE_SIZE);
> init_exp(size);
>
> /* Initialize in case they forgot to put in a clear code.
> * (This shouldn't happen, but we'll try and decode it anyway...)
> */
> oc = fc = 0;
>
> /* Allocate space for the decode buffer
> */
> if ((buf = (unsigned char *)malloc(linewidth + 1)) == NULL)
> return(OUT_OF_MEMORY);
>
> /* Set up the stack pointer and decode buffer pointer
> */
> sp = stack;
> bufptr = buf;
> bufcnt = linewidth;
>
> /* This is the main loop. For each code we get we pass through the
> * linked list of prefix codes, pushing the corresponding "character" for
> * each code onto the stack. When the list reaches a single "character"
> * we push that on the stack too, and then start unstacking each
> * character for output in the correct order. Special handling is
> * included for the clear code, and the whole thing ends when we get
> * an ending code.
> */
> while ((c = get_next_code()) != ending)
> {
>
> /* If we had a file error, return without completing the decode
> */
> if (c < 0)
> {
> free(buf);
> return(0);
> }
>
> /* If the code is a clear code, reinitialize all necessary items.
> */
> if (c == clear)
> {
> curr_size = size + 1;
> slot = newcodes;
> top_slot = 1 << curr_size;
>
> /* Continue reading codes until we get a non-clear code
> * (Another unlikely, but possible case...)
> */
> while ((c = get_next_code()) == clear)
> ;
>
> /* If we get an ending code immediately after a clear code
> * (Yet another unlikely case), then break out of the loop.
> */
> if (c == ending)
> break;
>
> /* Finally, if the code is beyond the range of already set codes,
> * (This one had better NOT happen... I have no idea what will
> * result from this, but I doubt it will look good...) then set it
> * to color zero.
> */
> if (c >= slot)
> c = 0;
>
> oc = fc = c;
>
> /* And let us not forget to put the char into the buffer... And
> * if, on the off chance, we were exactly one pixel from the end
> * of the line, we have to send the buffer to the out_line()
> * routine...
> */
> *bufptr++ = c;
> if (--bufcnt == 0)
> {
> if ((ret = out_line(buf, linewidth)) < 0)
> {
> free(buf);
> return(ret);
> }
> bufptr = buf;
> bufcnt = linewidth;
> }
> }
> else
> {
>
> /* In this case, it's not a clear code or an ending code, so
> * it must be a code code... So we can now decode the code into
> * a stack of character codes. (Clear as mud, right?)
> */
> code = c;
>
> /* Here we go again with one of those off chances... If, on the
> * off chance, the code we got is beyond the range of those already
> * set up (Another thing which had better NOT happen...) we trick
> * the decoder into thinking it actually got the last code read.
> * (Hmmn... I'm not sure why this works... But it does...)
> */
> if (code >= slot)
> {
> if (code > slot)
> ++bad_code_count;
> code = oc;
> *sp++ = fc;
> }
>
> /* Here we scan back along the linked list of prefixes, pushing
> * helpless characters (ie. suffixes) onto the stack as we do so.
> */
> while (code >= newcodes)
> {
> *sp++ = suffix[code];
> code = prefix[code];
> }
>
> /* Push the last character on the stack, and set up the new
> * prefix and suffix, and if the required slot number is greater
> * than that allowed by the current bit size, increase the bit
> * size. (NOTE - If we are all full, we *don't* save the new
> * suffix and prefix... I'm not certain if this is correct...
> * it might be more proper to overwrite the last code...
> */
> *sp++ = code;
> if (slot < top_slot)
> {
> suffix[slot] = fc = code;
> prefix[slot++] = oc;
> oc = c;
> }
> if (slot >= top_slot)
> if (curr_size < 12)
> {
> top_slot <<= 1;
> ++curr_size;
> }
>
> /* Now that we've pushed the decoded string (in reverse order)
> * onto the stack, lets pop it off and put it into our decode
> * buffer... And when the decode buffer is full, write another
> * line...
> */
> while (sp > stack)
> {
> *bufptr++ = *(--sp);
> if (--bufcnt == 0)
> {
> if ((ret = out_line(buf, linewidth)) < 0)
> {
> free(buf);
> return(ret);
> }
> bufptr = buf;
> bufcnt = linewidth;
> }
> }
> }
> }
> ret = 0;
> if (bufcnt != linewidth)
> ret = out_line(buf, (linewidth - bufcnt));
> free(buf);
> return(ret);
> }
>
>
> // this function is called just before program exits
> void cleanup(void){
> // free any allocated resources
> if(fp!=NULL)
> fclose(fp);
> if(buffer!=NULL)
> free(buffer);
> if(grgb!=NULL)
> free(grgb);
> if(lrgb!=NULL)
> free(lrgb);
> if(pixels!=NULL)
> free(pixels);
> }
>
> void main(int argc, char **argv){
> unsigned int gctsize=0, lctsize=0, mode;
> int i;
>
> // set bad codes encountered to zero
> bad_code_count=0;
>
> // set function to be called on exit
> if(atexit(cleanup))
> exit(0);
>
> // exit if no file given
> if (argc<2){
> printf("Usage: %s gif_file\n", argv[0]);
> exit(0);
> }
>
> // try to open file
> if((fp=fopen(argv[1], "rb"))==NULL){
> printf("Failed to open file.\n");
> exit(0);
> }
>
> // allocate buffers
> buffer=(unsigned char *)malloc(BSIZE);
> pixels=(unsigned char *)malloc(ISIZE);
> grgb =(unsigned char *)malloc(PSIZE);
> lrgb =(unsigned char *)malloc(PSIZE);
> if((grgb==NULL) || (lrgb==NULL) || (pixels==NULL) || (buffer==NULL)){
> printf("Not enough memory.\n");
> exit(0);
> }
>
> fread(buffer, 1, 6, fp);
> // test file for valid GIF signature
> if(memcmp(buffer, "GIF", 3)!=0){
> printf("Not a GIF file.\n");
> exit(0);
> }
> // test file for version number
> if((memcmp(buffer+3, "87a", 3)!=0) && (memcmp(buffer+3, "89a", 3)!=0)){
> printf("Unsuported GIF version. Hit a key to decode anyway.\n");
> getch();
> }
>
> // read logical screen descriptor
> fread(buffer, 1, 7, fp);
>
> // test for global color table presence
> if(*(buffer+4)&0x80){
> // compute global color table size
> gctsize=1<<((*(buffer+4)&0x07) + 1);
> // read global color table into buffer
> fread(grgb, 1, gctsize*3, fp);
> // adjust colors to crappy 6-bit PC-DAC values
> for(i=0; i<gctsize*3; i++)
> *(grgb+i)>>=2;
> }
> // get background color index
> background=*(buffer+5);
>
>
> // scan file for data blocks
> while((i=get_byte())>0) {
> // in end of GIF marker encountered then exit
> if(i==0x3b)
> exit(0);
> // test for extentions
> if(i==0x21){
> if( (i=get_byte()) < 0 )
> exit(0);
> // if graphic color extention present or
> // coment extention present or
> // plain text extention present or
> // application extention present then skip it
> if( (i==0x01) || (i==0xf9) || (i==0xfe) || (i==0xff)){
> while((i=get_byte())!=0){
> if(fread(buffer, 1, i, fp)!=i)
> exit(0);
> }
> }
> }
>
> // test for presence of image descriptor
> if(i==0x2c){
> // get image descriptor
> fread(buffer, 1, 9, fp);
> // interlaced flag is set or cleared accordingly
> if(*(buffer+8)&0x40)
> group=1;
> realx=xsize=*(buffer+4) | (*(buffer+5)<<8);
> realy=ysize=*(buffer+6) | (*(buffer+7)<<8);
> // test for presence of local color table
> if(*(buffer+8)&0x80){
> // compute local color table size
> lctsize=1<<((*(buffer+8)&0x07) + 1);
> // read local color table into buffer
> fread(lrgb, 1, lctsize*3, fp);
> // adjust colors to crappy 6-bit PC-DAC values
> for(i=0; i<gctsize*3; i++)
> *(lrgb+i)>>=2;
> }
>
> // choose a video mode that will just fit the image
> if((xsize<=640) && (ysize<=480)){
> mode=0x101; // VESA 640 x 480 x 256
> xsize=640;
> ysize=480;
> } else if ((xsize<=800) && (ysize<=600)){
> mode=0x103; // VESA 800 x 600 x 256
> xsize=800;
> ysize=600;
> } else if ((xsize<=1024) && (ysize<=768)){
> mode=0x105; // VESA 1024 x 768 x 256
> xsize=1024;
> ysize=768;
> } else {
> mode=0x107; // VESA 1280 x 1024 x 256
> xsize=1280;
> ysize=1024;
> }
>
> piclen=(unsigned long)xsize*(unsigned long)ysize;
> // get video mode info through VESA call
> asm pusha
> asm mov ax, 0x4f01
> asm mov cx, mode
> asm les di, buffer
> asm int 0x10
> asm mov i, ax
> asm popa
>
> if(i!=0x004f){
> printf("VESA video functions not available.\n");
> exit(0);
> }
> // if mode not supported, or not color, or not graphics then exit
> if((*buffer&0x19)!=0x19){
> printf("Required graphics mode is not available.\n");
> exit(0);
> }
>
> // if window does not exist or is not writable exit
> if((*(buffer+2)&0x05)!=0x05) {
> printf("Cannot access video RAM.\n");
> exit(0);
> }
>
> // calculate window granularity
> granularity=(*(buffer+4) | (*(buffer+5)<<8))<<10;
> // calculate pointer to video RAM start
> vid=(unsigned char *)MK_FP((*(buffer+8) | (*(buffer+9)<<8)), 0);
>
> // set VESA video mode
> asm pusha
> asm mov ax, 0x4f02
> asm mov bx, mode
> asm int 0x10
> asm popa
>
> // set color table if present
> if(lctsize){
> // scope of local color table is local so once used it's gone
> lctsize=0;
> asm pusha
> asm mov ax, 0x1012
> asm mov bx, 0x0000
> asm mov cx, 0x0100
> asm les dx, lrgb
> asm int 0x10
> asm popa
> } else if(gctsize){
> // if no local color table then set global color table if present
> asm pusha
> asm mov ax, 0x1012
> asm mov bx, 0x0000
> asm mov cx, 0x0100
> asm les dx, grgb
> asm int 0x10
> asm pop es
> asm popa
> }
>
> // decode and display graphic
> decode(realx);
> // wait for key press
> getch();
>
> // set default text mode
> asm mov ax, 0x0003
> asm int 0x10
> }
> }
>
> // exit to dos
> exit(0);
> }
>
> -------------- chop here -------------------
>
> --
> +-----------------------------+-----------------------------------------------+
> | Alex Ivopol | If you love something set it free. If it |
> | cyborg@akeake.its.vuw.ac.nz | doesn't come back, hunt it down and kill it. |
> +-----------------------------+-----------------------------------------------+
== 2 of 4 ==
Date: Wed, Jan 8 2014 7:33 pm
From: Ian Collins
kirannd1989@gmail.com wrote:
> Hi..
> i tried compiling this code but there are few undefined Macro/functions like MK_FP().
> I am trying it on WIN32, VS2012.. i have made changes accordingly.
> Is this solution dependent on any library.
> Thanks in advance
>
>
> On Monday, August 1, 1994 1:02:48 PM UTC+5:30, Cyborg wrote:
Are you going for the record for the oldest post to reply to?
--
Ian Collins
== 3 of 4 ==
Date: Wed, Jan 8 2014 10:05 pm
From: Johann Klammer
kirannd1989@gmail.com wrote:
> Hi..
> i tried compiling this code but there are few undefined Macro/functions like MK_FP().
> I am trying it on WIN32, VS2012.. i have made changes accordingly.
> Is this solution dependent on any library.
> Thanks in advance
>
>
> On Monday, August 1, 1994 1:02:48 PM UTC+5:30, Cyborg wrote:
>> In article<msm6.775622996@ra.msstate.edu> msm6@Ra.MsState.Edu (Muhammad Salman Mughal) writes:
>>>
>>> Hi there,
>>>
>>> I am desperately looking for a C code that could decode a GIF file
>>> in DOS. Anybody out there who knows how to do it? I will really
>>> appreciate any help.
>>>
>>
>>
>> The following code is based on a LZW decoder originally coded by Steven A.
>> Bennett. All I did is write the code for parsing the GIF format, passing
>> the approptiate data to the LZW decoder and writing the code for displaying
>> the data on the screen. Both 87a and 89a formats are accepted.
>>
>> Video BIOS must support VESA functions - the code selects a video mode
>> whith a resolution just high enough to display the given GIF file. Max
>> resolution is 1280x1024, pictures larger than this will be partially
>> displayed. Interlaced GIFs are supported. Program was only tested on my
>> video card (Cirrus 5428 VESA Local Bus). It was not intended for public
>> release but since I've already written it and the guy i desperate...
>>
>> Compiles with Borland C++ v3.1
>>
>> ----------------------- chop here --------------------------
>>
>> /* Various error codes used by decoder
>> * and my own routines... It's okay
>> * for you to define whatever you want,
>> * as long as it's negative... It will be
>> * returned intact up the various subroutine
>> * levels...
>> */
>> #define READ_ERROR -1
>> #define WRITE_ERROR -2
>> #define OPEN_ERROR -3
>> #define CREATE_ERROR -4
>> #define OUT_OF_MEMORY -5
>> #define BAD_CODE_SIZE -6
>>
>> #define ISIZE 2048 // image line size
>> #define BSIZE 256 // buffer size
>> #define PSIZE 768 // pallette size
>> #define NULL 0L
>> #define MAX_CODES 4095
>>
>> #include<dos.h>
>> #include<conio.h>
>> #include<stdio.h>
>> #include<stdlib.h>
>> #include<string.h>
>>
>> /* Static variables */
>> short curr_size; /* The current code size */
>> short clear; /* Value for a clear code */
>> short ending; /* Value for a ending code */
>> short newcodes; /* First available code */
>> short top_slot; /* Highest code for current size */
>> short slot; /* Last read code */
>>
>> /* The following static variables are used
>> * for seperating out codes
>> */
>> short navail_bytes = 0; /* # bytes left in block */
>> short nbits_left = 0; /* # bits left in current byte */
>> unsigned char b1; /* Current byte */
>> unsigned char byte_buff[257]; /* Current block */
>> unsigned char *pbytes; /* Pointer to next byte in block */
>>
>> /* The reason we have these separated like this instead of using
>> * a structure like the original Wilhite code did, is because this
>> * stuff generally produces significantly faster code when compiled...
>> * This code is full of similar speedups... (For a good book on writing
>> * C for speed or for space optimisation, see Efficient C by Tom Plum,
>> * published by Plum-Hall Associates...)
>> */
>> unsigned char stack[MAX_CODES + 1]; /* Stack for storing pixels */
>> unsigned char suffix[MAX_CODES + 1]; /* Suffix table */
>> unsigned short prefix[MAX_CODES + 1]; /* Prefix linked list */
>>
>> long code_mask[13] = {
>> 0x0000,
>> 0x0001, 0x0003, 0x0007, 0x000F,
>> 0x001F, 0x003F, 0x007F, 0x00FF,
>> 0x01FF, 0x03FF, 0x07FF, 0x0FFF
>> };
>>
>> // incremented each time an out of range code is read by the decoder
>> int bad_code_count;
>>
>> unsigned char far *buffer=NULL; // file buffer
>> unsigned char far *grgb=NULL; // global rgb table
>> unsigned char far *lrgb=NULL; // local rgb table
>> unsigned char far *pixels=NULL; // line of pixels to be displayed
>> unsigned char far *vid=NULL; // ptr to start of graphics window
>> unsigned char background=0; // background color index
>> unsigned long offset=0; // offset into graphics window
>> unsigned long piclen; // total screen size in pixels
>> unsigned int realx; // real picture width
>> unsigned int realy; // real picture height
>> unsigned int xsize=0; // graphic width
>> unsigned int ysize=0; // graphic height
>> unsigned int win=0; // window number
>> unsigned int granularity=0; // granularity of video window
>> unsigned int group=0; // picture group (interlaced or not)
>> FILE *fp; // file pointer
>>
>> /* int get_byte()
>> * - This function is expected to return the next byte from
>> * the GIF file or a negative number defined in ERRS.H
>> */
>> int get_byte(){
>> unsigned char c;
>>
>> if(fscanf(fp, "%c",&c)==1)
>> return((int)c);
>> else
>> return(READ_ERROR);
>> }
>>
>> /* int out_line(unsigned char pixels[], int linelen)
>> * - This function takes a full line of pixels (one byte per pixel) and
>> * displays them (or does whatever your program wants with them...). It
>> * should return zero, or negative if an error or some other event occurs
>> * which would require aborting the decode process... Note that the length
>> * passed will almost always be equal to the line length passed to the
>> * decoder function, with the sole exception occurring when an ending code
>> * occurs in an odd place in the GIF file... In any case, linelen will be
>> * equal to the number of pixels passed...
>> */
>> int out_line(unsigned char *pixels, int linelen){
>> unsigned long segment;
>>
>> segment=offset&(unsigned long)(granularity-1);
>>
>> // put pixels on screen
>> memmove(vid+segment, pixels, linelen);
>> memset(vid+segment+linelen, background, xsize-linelen);
>> switch (group) {
>> case 0:
>> offset+=xsize;
>> break;
>> case 1:
>> offset+=xsize*8;
>> if(offset>=piclen){
>> group++;
>> offset=xsize*4;
>> }
>> break;
>> case 2:
>> offset+=xsize*8;
>> if(offset>=piclen){
>> group++;
>> offset=xsize*2;
>> }
>> break;
>> case 3:
>> offset+=xsize*4;
>> if(offset>=piclen){
>> group++;
>> offset=xsize;
>> }
>> break;
>> case 4:
>> offset+=xsize*2;
>> break;
>> default:
>> break;
>> }
>>
>> // if we've run over a window granularity border, move window position
>> if((offset>>12)!=win){
>> win=offset>>12;
>> asm pusha
>> asm mov ax, 0x4f05
>> asm mov bx, 0x0000
>> asm mov dx, win
>> asm int 0x10
>> asm popa
>> }
>> return(1);
>> }
>>
>>
>> /* This function initializes the decoder for reading a new image.
>> */
>> static short init_exp(short size)
>> {
>> curr_size = size + 1;
>> top_slot = 1<< curr_size;
>> clear = 1<< size;
>> ending = clear + 1;
>> slot = newcodes = ending + 1;
>> navail_bytes = nbits_left = 0;
>> return(0);
>> }
>>
>> /* get_next_code()
>> * - gets the next code from the GIF file. Returns the code, or else
>> * a negative number in case of file errors...
>> */
>> static short get_next_code()
>> {
>> short i, x;
>> unsigned long ret;
>>
>> if (nbits_left == 0)
>> {
>> if (navail_bytes<= 0)
>> {
>>
>> /* Out of bytes in current block, so read next block
>> */
>> pbytes = byte_buff;
>> if ((navail_bytes = get_byte())< 0)
>> return(navail_bytes);
>> else if (navail_bytes)
>> {
>> for (i = 0; i< navail_bytes; ++i)
>> {
>> if ((x = get_byte())< 0)
>> return(x);
>> byte_buff[i] = x;
>> }
>> }
>> }
>> b1 = *pbytes++;
>> nbits_left = 8;
>> --navail_bytes;
>> }
>>
>> ret = b1>> (8 - nbits_left);
>> while (curr_size> nbits_left)
>> {
>> if (navail_bytes<= 0)
>> {
>>
>> /* Out of bytes in current block, so read next block
>> */
>> pbytes = byte_buff;
>> if ((navail_bytes = get_byte())< 0)
>> return(navail_bytes);
>> else if (navail_bytes)
>> {
>> for (i = 0; i< navail_bytes; ++i)
>> {
>> if ((x = get_byte())< 0)
>> return(x);
>> byte_buff[i] = x;
>> }
>> }
>> }
>> b1 = *pbytes++;
>> ret |= b1<< nbits_left;
>> nbits_left += 8;
>> --navail_bytes;
>> }
>> nbits_left -= curr_size;
>> ret&= code_mask[curr_size];
>> return((short)(ret));
>> }
>>
>> /* DECODE.C - An LZW decoder for GIF
>> *
>> * Copyright (C) 1987, by Steven A. Bennett
>> *
>> * Permission is given by the author to freely redistribute and include
>> * this code in any program as long as this credit is given where due.
>> *
>> * In accordance with the above, I want to credit Steve Wilhite who wrote
>> * the code which this is heavily inspired by...
>> *
>> * GIF and 'Graphics Interchange Format' are trademarks (tm) of
>> * Compuserve, Incorporated, an H&R Block Company.
>> *
>> * Release Notes: This file contains a decoder routine for GIF images
>> * which is similar, structurally, to the original routine by Steve Wilhite.
>> * It is, however, somewhat noticably faster in most cases.
>> *
>> * short decode(linewidth)
>> * short linewidth; * Pixels per line of image *
>> *
>> * - This function decodes an LZW image, according to the method used
>> * in the GIF spec. Every *linewidth* "characters" (ie. pixels) decoded
>> * will generate a call to out_line(), which is a user specific function
>> * to display a line of pixels. The function gets it's codes from
>> * get_next_code() which is responsible for reading blocks of data and
>> * seperating them into the proper size codes. Finally, get_byte() is
>> * the global routine to read the next byte from the GIF file.
>> *
>> * It is generally a good idea to have linewidth correspond to the actual
>> * width of a line (as specified in the Image header) to make your own
>> * code a bit simpler, but it isn't absolutely necessary.
>> *
>> * Returns: 0 if successful, else negative. (See ERRS.H)
>> *
>> */
>>
>> short decode(short linewidth)
>> {
>> register unsigned char *sp, *bufptr;
>> unsigned char *buf;
>> register short code, fc, oc, bufcnt;
>> short c, size, ret;
>>
>> /* Initialize for decoding a new image...
>> */
>> if ((size = get_byte())< 0)
>> return(size);
>> if (size< 2 || 9< size)
>> return(BAD_CODE_SIZE);
>> init_exp(size);
>>
>> /* Initialize in case they forgot to put in a clear code.
>> * (This shouldn't happen, but we'll try and decode it anyway...)
>> */
>> oc = fc = 0;
>>
>> /* Allocate space for the decode buffer
>> */
>> if ((buf = (unsigned char *)malloc(linewidth + 1)) == NULL)
>> return(OUT_OF_MEMORY);
>>
>> /* Set up the stack pointer and decode buffer pointer
>> */
>> sp = stack;
>> bufptr = buf;
>> bufcnt = linewidth;
>>
>> /* This is the main loop. For each code we get we pass through the
>> * linked list of prefix codes, pushing the corresponding "character" for
>> * each code onto the stack. When the list reaches a single "character"
>> * we push that on the stack too, and then start unstacking each
>> * character for output in the correct order. Special handling is
>> * included for the clear code, and the whole thing ends when we get
>> * an ending code.
>> */
>> while ((c = get_next_code()) != ending)
>> {
>>
>> /* If we had a file error, return without completing the decode
>> */
>> if (c< 0)
>> {
>> free(buf);
>> return(0);
>> }
>>
>> /* If the code is a clear code, reinitialize all necessary items.
>> */
>> if (c == clear)
>> {
>> curr_size = size + 1;
>> slot = newcodes;
>> top_slot = 1<< curr_size;
>>
>> /* Continue reading codes until we get a non-clear code
>> * (Another unlikely, but possible case...)
>> */
>> while ((c = get_next_code()) == clear)
>> ;
>>
>> /* If we get an ending code immediately after a clear code
>> * (Yet another unlikely case), then break out of the loop.
>> */
>> if (c == ending)
>> break;
>>
>> /* Finally, if the code is beyond the range of already set codes,
>> * (This one had better NOT happen... I have no idea what will
>> * result from this, but I doubt it will look good...) then set it
>> * to color zero.
>> */
>> if (c>= slot)
>> c = 0;
>>
>> oc = fc = c;
>>
>> /* And let us not forget to put the char into the buffer... And
>> * if, on the off chance, we were exactly one pixel from the end
>> * of the line, we have to send the buffer to the out_line()
>> * routine...
>> */
>> *bufptr++ = c;
>> if (--bufcnt == 0)
>> {
>> if ((ret = out_line(buf, linewidth))< 0)
>> {
>> free(buf);
>> return(ret);
>> }
>> bufptr = buf;
>> bufcnt = linewidth;
>> }
>> }
>> else
>> {
>>
>> /* In this case, it's not a clear code or an ending code, so
>> * it must be a code code... So we can now decode the code into
>> * a stack of character codes. (Clear as mud, right?)
>> */
>> code = c;
>>
>> /* Here we go again with one of those off chances... If, on the
>> * off chance, the code we got is beyond the range of those already
>> * set up (Another thing which had better NOT happen...) we trick
>> * the decoder into thinking it actually got the last code read.
>> * (Hmmn... I'm not sure why this works... But it does...)
>> */
>> if (code>= slot)
>> {
>> if (code> slot)
>> ++bad_code_count;
>> code = oc;
>> *sp++ = fc;
>> }
>>
>> /* Here we scan back along the linked list of prefixes, pushing
>> * helpless characters (ie. suffixes) onto the stack as we do so.
>> */
>> while (code>= newcodes)
>> {
>> *sp++ = suffix[code];
>> code = prefix[code];
>> }
>>
>> /* Push the last character on the stack, and set up the new
>> * prefix and suffix, and if the required slot number is greater
>> * than that allowed by the current bit size, increase the bit
>> * size. (NOTE - If we are all full, we *don't* save the new
>> * suffix and prefix... I'm not certain if this is correct...
>> * it might be more proper to overwrite the last code...
>> */
>> *sp++ = code;
>> if (slot< top_slot)
>> {
>> suffix[slot] = fc = code;
>> prefix[slot++] = oc;
>> oc = c;
>> }
>> if (slot>= top_slot)
>> if (curr_size< 12)
>> {
>> top_slot<<= 1;
>> ++curr_size;
>> }
>>
>> /* Now that we've pushed the decoded string (in reverse order)
>> * onto the stack, lets pop it off and put it into our decode
>> * buffer... And when the decode buffer is full, write another
>> * line...
>> */
>> while (sp> stack)
>> {
>> *bufptr++ = *(--sp);
>> if (--bufcnt == 0)
>> {
>> if ((ret = out_line(buf, linewidth))< 0)
>> {
>> free(buf);
>> return(ret);
>> }
>> bufptr = buf;
>> bufcnt = linewidth;
>> }
>> }
>> }
>> }
>> ret = 0;
>> if (bufcnt != linewidth)
>> ret = out_line(buf, (linewidth - bufcnt));
>> free(buf);
>> return(ret);
>> }
>>
>>
>> // this function is called just before program exits
>> void cleanup(void){
>> // free any allocated resources
>> if(fp!=NULL)
>> fclose(fp);
>> if(buffer!=NULL)
>> free(buffer);
>> if(grgb!=NULL)
>> free(grgb);
>> if(lrgb!=NULL)
>> free(lrgb);
>> if(pixels!=NULL)
>> free(pixels);
>> }
>>
>> void main(int argc, char **argv){
>> unsigned int gctsize=0, lctsize=0, mode;
>> int i;
>>
>> // set bad codes encountered to zero
>> bad_code_count=0;
>>
>> // set function to be called on exit
>> if(atexit(cleanup))
>> exit(0);
>>
>> // exit if no file given
>> if (argc<2){
>> printf("Usage: %s gif_file\n", argv[0]);
>> exit(0);
>> }
>>
>> // try to open file
>> if((fp=fopen(argv[1], "rb"))==NULL){
>> printf("Failed to open file.\n");
>> exit(0);
>> }
>>
>> // allocate buffers
>> buffer=(unsigned char *)malloc(BSIZE);
>> pixels=(unsigned char *)malloc(ISIZE);
>> grgb =(unsigned char *)malloc(PSIZE);
>> lrgb =(unsigned char *)malloc(PSIZE);
>> if((grgb==NULL) || (lrgb==NULL) || (pixels==NULL) || (buffer==NULL)){
>> printf("Not enough memory.\n");
>> exit(0);
>> }
>>
>> fread(buffer, 1, 6, fp);
>> // test file for valid GIF signature
>> if(memcmp(buffer, "GIF", 3)!=0){
>> printf("Not a GIF file.\n");
>> exit(0);
>> }
>> // test file for version number
>> if((memcmp(buffer+3, "87a", 3)!=0)&& (memcmp(buffer+3, "89a", 3)!=0)){
>> printf("Unsuported GIF version. Hit a key to decode anyway.\n");
>> getch();
>> }
>>
>> // read logical screen descriptor
>> fread(buffer, 1, 7, fp);
>>
>> // test for global color table presence
>> if(*(buffer+4)&0x80){
>> // compute global color table size
>> gctsize=1<<((*(buffer+4)&0x07) + 1);
>> // read global color table into buffer
>> fread(grgb, 1, gctsize*3, fp);
>> // adjust colors to crappy 6-bit PC-DAC values
>> for(i=0; i<gctsize*3; i++)
>> *(grgb+i)>>=2;
>> }
>> // get background color index
>> background=*(buffer+5);
>>
>>
>> // scan file for data blocks
>> while((i=get_byte())>0) {
>> // in end of GIF marker encountered then exit
>> if(i==0x3b)
>> exit(0);
>> // test for extentions
>> if(i==0x21){
>> if( (i=get_byte())< 0 )
>> exit(0);
>> // if graphic color extention present or
>> // coment extention present or
>> // plain text extention present or
>> // application extention present then skip it
>> if( (i==0x01) || (i==0xf9) || (i==0xfe) || (i==0xff)){
>> while((i=get_byte())!=0){
>> if(fread(buffer, 1, i, fp)!=i)
>> exit(0);
>> }
>> }
>> }
>>
>> // test for presence of image descriptor
>> if(i==0x2c){
>> // get image descriptor
>> fread(buffer, 1, 9, fp);
>> // interlaced flag is set or cleared accordingly
>> if(*(buffer+8)&0x40)
>> group=1;
>> realx=xsize=*(buffer+4) | (*(buffer+5)<<8);
>> realy=ysize=*(buffer+6) | (*(buffer+7)<<8);
>> // test for presence of local color table
>> if(*(buffer+8)&0x80){
>> // compute local color table size
>> lctsize=1<<((*(buffer+8)&0x07) + 1);
>> // read local color table into buffer
>> fread(lrgb, 1, lctsize*3, fp);
>> // adjust colors to crappy 6-bit PC-DAC values
>> for(i=0; i<gctsize*3; i++)
>> *(lrgb+i)>>=2;
>> }
>>
>> // choose a video mode that will just fit the image
>> if((xsize<=640)&& (ysize<=480)){
>> mode=0x101; // VESA 640 x 480 x 256
>> xsize=640;
>> ysize=480;
>> } else if ((xsize<=800)&& (ysize<=600)){
>> mode=0x103; // VESA 800 x 600 x 256
>> xsize=800;
>> ysize=600;
>> } else if ((xsize<=1024)&& (ysize<=768)){
>> mode=0x105; // VESA 1024 x 768 x 256
>> xsize=1024;
>> ysize=768;
>> } else {
>> mode=0x107; // VESA 1280 x 1024 x 256
>> xsize=1280;
>> ysize=1024;
>> }
>>
>> piclen=(unsigned long)xsize*(unsigned long)ysize;
>> // get video mode info through VESA call
>> asm pusha
>> asm mov ax, 0x4f01
>> asm mov cx, mode
>> asm les di, buffer
>> asm int 0x10
>> asm mov i, ax
>> asm popa
>>
>> if(i!=0x004f){
>> printf("VESA video functions not available.\n");
>> exit(0);
>> }
>> // if mode not supported, or not color, or not graphics then exit
>> if((*buffer&0x19)!=0x19){
>> printf("Required graphics mode is not available.\n");
>> exit(0);
>> }
>>
>> // if window does not exist or is not writable exit
>> if((*(buffer+2)&0x05)!=0x05) {
>> printf("Cannot access video RAM.\n");
>> exit(0);
>> }
>>
>> // calculate window granularity
>> granularity=(*(buffer+4) | (*(buffer+5)<<8))<<10;
>> // calculate pointer to video RAM start
>> vid=(unsigned char *)MK_FP((*(buffer+8) | (*(buffer+9)<<8)), 0);
>>
>> // set VESA video mode
>> asm pusha
>> asm mov ax, 0x4f02
>> asm mov bx, mode
>> asm int 0x10
>> asm popa
>>
>> // set color table if present
>> if(lctsize){
>> // scope of local color table is local so once used it's gone
>> lctsize=0;
>> asm pusha
>> asm mov ax, 0x1012
>> asm mov bx, 0x0000
>> asm mov cx, 0x0100
>> asm les dx, lrgb
>> asm int 0x10
>> asm popa
>> } else if(gctsize){
>> // if no local color table then set global color table if present
>> asm pusha
>> asm mov ax, 0x1012
>> asm mov bx, 0x0000
>> asm mov cx, 0x0100
>> asm les dx, grgb
>> asm int 0x10
>> asm pop es
>> asm popa
>> }
>>
>> // decode and display graphic
>> decode(realx);
>> // wait for key press
>> getch();
>>
>> // set default text mode
>> asm mov ax, 0x0003
>> asm int 0x10
>> }
>> }
>>
>> // exit to dos
>> exit(0);
>> }
>>
>> -------------- chop here -------------------
>>
>> --
>> +-----------------------------+-----------------------------------------------+
>> | Alex Ivopol | If you love something set it free. If it |
>> | cyborg@akeake.its.vuw.ac.nz | doesn't come back, hunt it down and kill it. |
>> +-----------------------------+-----------------------------------------------+
Dear people from the future,
The code does direct hardware access to gfx card(VESA for mode-setting
and output). The MK_FP is problematic, too(16 bit dos program). The
output is pallettized and 6 bits per components(r,g,b). You'll most
likely want 8. Aside from those details it might work alright. You will
need another way to actually display the decoded data. there have been
help files floating around the net documenting M$ win32 API. try those.
Also...
http://www.winprog.org/tutorial/
== 4 of 4 ==
Date: Wed, Jan 8 2014 10:27 pm
From: "Alf P. Steinbach"
On 09.01.2014 04:23, kirannd1989@gmail.com wrote:
> Hi..
> i tried compiling this code but there are few undefined Macro/functions like MK_FP().
> I am trying it on WIN32, VS2012.. i have made changes accordingly.
> Is this solution dependent on any library.
[snip early 1990's code]
No, the code is just very DOS-specific. It contains inline assembly for
a PC, with the program running with the processor in 8086 mode. In this
mode a logical address consists of a 16-bit offset and a 16-bit segment
selector. The segment selector could be implied, then taken from a
processor register. This (a 16-bit logical address specified as only
offset) was called a NEAR address. Alternatively the segment selector
could be explicitly specified, and this (a 32-bit logical address
specified as offset and selector) was called a FAR address.
Worth noting that a FAR address only specified 21 bits, because a
selector S always selected the logical segment starting at address 16*S.
MK_FP created a C language representation of a "far pointer".
There is nothing corresponding to that[1] in modern C or C++.
* * *
You may still be able to use the code, either directly in a DOS box (the
DOS emulator, not a Windows command interpreter instance) or by
replacing the DOS presentation with whatever you want.
Cheers & hth.,
- Alf
Notes:
[1] In still much used 32-bit C and C++ programming on the PC there is a
corresponding issue, namely that all addresses handled by C or C++
pointers are really just 32-bit offsets into a segment. The implied
segment selector can come from any relevant selector register because
the operating places the same selector value in all these registers (a
neat little trick). In order to access some Windows thread information
it's necessary to specify a different segment than the usual, namely the
one denoted by the FS register, if I recall correctly. To do this one
must delve down to the assembly language level.
==============================================================================
TOPIC: different rounding behavior with float and double
http://groups.google.com/group/comp.lang.c++/t/05d32024f4d7a3b9?hl=en
==============================================================================
== 1 of 7 ==
Date: Thurs, Jan 9 2014 1:46 am
From: Raymond Li
I have encountered a problem related to floating point rounding. I
googled a lot and there are many clear and helpful information. e.g.
http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/
http://support.microsoft.com/kb/125056/en-hk
Although the urls have explained the cause, I need to find a practical
way to solve a rounding problem. My program has calculated a weighted
accumulation as 3.5. When the figure is rounded to nearest number, it
became 3 (but I want it to round up to 4). I understood it would be due
to approximation value of 3.5 as 3.49999...
I found a simple fix by using float instead of double. I list the
program below and wish someone could explain why using double would
incur the rounding problem while float would not. In the code below,
fun1() use float and the calculation is 'correct'. In fun2(), it uses
double and the figure 3.5 is rounded as 3.
Raymond
//######################
#include <cmath>
#include <iostream>
//using namespace std;
using std::cout;
using std::endl;
int fun1();
int fun2();
int main(int argc, char ** argv)
{
fun1();
fun2();
return 0;
}
int fun1()
{
float weighted=10.0;
float average=100.0;
float z[]=
{
4.0,
4.0,
4.0,
4.0,
4.0,
3.0,
3.0,
3.0,
2.0,
4.0
};
float total=0.0;
int i=0;
for (i=0;i<10;i++)
{
float item=z[i]*weighted/average;
total=total+item;
cout << i << " accumulate is " << total << endl;
// NSLog(@"z[%d] is %f, total is %f", i, z[i], total);
}
float answer=round(total);
// NSLog(@"rounded is %f", answer);
cout << "rounded is " << answer << endl;
return 0;
}
int fun2()
{
double weighted=10.0;
double average=100.0;
double z[]=
{
4.0,
4.0,
4.0,
4.0,
4.0,
3.0,
3.0,
3.0,
2.0,
4.0
};
double total=0.0;
int i=0;
for (i=0;i<10;i++)
{
double item=z[i]*weighted/average;
total=total+item;
cout << i << " accumulate is " << total << endl;
// NSLog(@"z[%d] is %f, total is %f", i, z[i], total);
}
double answer=round(total);
// NSLog(@"rounded is %f", answer);
cout << "rounded is " << answer << endl;
return 0;
}
0 accumulate is 0.4
1 accumulate is 0.8
2 accumulate is 1.2
3 accumulate is 1.6
4 accumulate is 2
5 accumulate is 2.3
6 accumulate is 2.6
7 accumulate is 2.9
8 accumulate is 3.1
9 accumulate is 3.5
rounded is 4
***(above is the version using float, 3.5 is rounded as 4) ***
0 accumulate is 0.4
1 accumulate is 0.8
2 accumulate is 1.2
3 accumulate is 1.6
4 accumulate is 2
5 accumulate is 2.3
6 accumulate is 2.6
7 accumulate is 2.9
8 accumulate is 3.1
9 accumulate is 3.5
rounded is 3
***(this version use double, 3.5 is rounded as 3) ***
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
== 2 of 7 ==
Date: Thurs, Jan 9 2014 3:48 am
From: "Alf P. Steinbach"
On 09.01.2014 10:46, Raymond Li wrote:
>
> My program has calculated a weighted
> accumulation as 3.5. When the figure is rounded to nearest number, it
> became 3 (but I want it to round up to 4). I understood it would be due
> to approximation value of 3.5 as 3.49999...
round(x) rounds to the /nearest/ integer value of the type.
When x is around 3.5, as in your case, very tiny differences can make 3
or 4 the nearest integer. These tiny differences can be, well,
different, for float and double types (the latter has double the
precision, roughly).
If you want to round to 1 decimal fractional digit, then simply do this:
round( 10*x )/10
Or you can define that as a function:
auto rounded( double x, int n_decimals = 2 )
-> double
{
double const pow_of_10 = pow( 10.0, n_decimals );
return round( pow_of_10*x )/pow_of_ten;
}
Now regarding the choice of data type I (strongly) suggest to use
double, because that's the default and least troublesome in C++.
For example, a literal such as 3.14 is a double, and C style functions
such as printf and scanf work with double values.
Cheers & hth.,
- Alf
== 3 of 7 ==
Date: Thurs, Jan 9 2014 4:21 am
From: ram@zedat.fu-berlin.de (Stefan Ram)
Raymond Li <faihk1@gmail.com> writes:
>I found a simple fix by using float instead of double. I list the
>program below and wish someone could explain why using double would
>incur the rounding problem while float would not. In the code below,
>fun1() use float and the calculation is 'correct'. In fun2(), it uses
>double and the figure 3.5 is rounded as 3.
In this special case, the result might be correct using
float, but on the average (for random double values as
input) double will be correct more often.
When the input is (2,3,3,3,4,4,4,4,4,4), the average is 35/10,
so a human can work out the result and see that it should
be rounded to 4, so that a result of 3 might be disturbing.
But in the general case, when the input consists of random
double values, a human computer cannot do much better than
an electronic computer using double.
The electronic computer could use integer fraction arithmetics
to handle such special cases as (2,3,3,3,4,4,4,4,4,4), where
division by powers of ten or similar divisions occur to get
exactly the result as a human and double arithmetics in all
other cases.
== 4 of 7 ==
Date: Thurs, Jan 9 2014 5:58 am
From: Richard Damon
On 1/9/14, 4:46 AM, Raymond Li wrote:
> I have encountered a problem related to floating point rounding. I
> googled a lot and there are many clear and helpful information. e.g.
>
> http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/
> http://support.microsoft.com/kb/125056/en-hk
>
>
> Although the urls have explained the cause, I need to find a practical
> way to solve a rounding problem. My program has calculated a weighted
> accumulation as 3.5. When the figure is rounded to nearest number, it
> became 3 (but I want it to round up to 4). I understood it would be due
> to approximation value of 3.5 as 3.49999...
>
> I found a simple fix by using float instead of double. I list the
> program below and wish someone could explain why using double would
> incur the rounding problem while float would not. In the code below,
> fun1() use float and the calculation is 'correct'. In fun2(), it uses
> double and the figure 3.5 is rounded as 3.
>
> Raymond
>
>
This program is effectively calculating something like
.4 + .4 + .4 + .4 + .4 + .3 + .3 + .3 + .2 + .4
Note that none of these values can be exactly expresses as a float or
double so we get numerous round off errors.
If instead you computed it as
(4.0 + 4.0 + 4.0 + 4.0 + 4.0 + 3.0 + 3.0 + 3.0 + 2.0 + 4.0)/10.0
Then each number (having the value of a small integer) can be exactly
represented as a double, and the result will be exact (since the result
3.5 = 7/2 is an exact binary fraction, unlike 4/10)
You only notice this round off error because your input numbers and
weighting factors are "nice" numbers so you can mentally to the math
exactly. Since the answer is very near a discontinuity (the .5 break
point of round), the result is very sensitive to small errors in
calculation.
If the numbers were more realistically not so precisely "round" numbers,
you are much less apt to hit this sort of discontinuous behavior in a
noticeable way.
If the input numbers ARE expected to this sort of nice number, then you
need to be very careful how you do your math to avoid creating "not
nice" numbers along the way creating round of error. Not nice numbers
are numbers line .4 which aren't a reasonable integral multiple of a
power of 2 (note that 1 is a power of 2, being 2 to the 0th power, so
integral numbers are nice, decimal fractions are generally not nice,
unless they are things like .5, .25, .375, which are decimal equivalents
of simple binary fractions).
When you have "nice" numbers, you can add them, subtract them, or
multiply them (within reason) and stay "nice", dividing will likely
break nice, unless you are dividing by a power of 2, so algorithms that
maximize accuracy for "nice" numbers need to avoid dividing as much as
possible, and make it as late a possible.
== 5 of 7 ==
Date: Thurs, Jan 9 2014 6:14 am
From: Wouter van Ooijen
> This program is effectively calculating something like
>
> .4 + .4 + .4 + .4 + .4 + .3 + .3 + .3 + .2 + .4
>
> Note that none of these values can be exactly expresses as a float or
> double so we get numerous round off errors.
>
> If instead you computed it as
>
> (4.0 + 4.0 + 4.0 + 4.0 + 4.0 + 3.0 + 3.0 + 3.0 + 2.0 + 4.0)/10.0
>
> Then each number (having the value of a small integer) can be exactly
> represented as a double, and the result will be exact (since the result
> 3.5 = 7/2 is an exact binary fraction, unlike 4/10)
If this is indeed about such a set of numbers the obvious solution would
be to scale all values up to integers.
Wouter
== 6 of 7 ==
Date: Thurs, Jan 9 2014 11:11 am
From: Stuart
On 01/09/14, Wouter van Ooijen wrote:
>> This program is effectively calculating something like
>>
>> .4 + .4 + .4 + .4 + .4 + .3 + .3 + .3 + .2 + .4
>>
>> Note that none of these values can be exactly expresses as a float or
>> double so we get numerous round off errors.
>>
>> If instead you computed it as
>>
>> (4.0 + 4.0 + 4.0 + 4.0 + 4.0 + 3.0 + 3.0 + 3.0 + 2.0 + 4.0)/10.0
>>
>> Then each number (having the value of a small integer) can be exactly
>> represented as a double, and the result will be exact (since the result
>> 3.5 = 7/2 is an exact binary fraction, unlike 4/10)
>
> If this is indeed about such a set of numbers the obvious solution would
> be to scale all values up to integers.
IMHO, the obvious solution would be to use a programming language that
takes care of such messy conversions, like Ada95. Ada lets you define
fixed point numbers type so that the actual computation will be done
through integer arithmetic. Ada has a real type system even for
primitive types like int and float, not the C typedef crap. I wish that
this would exist for C++, too, but I'm afraid that such a feature will
never make it into the C++ standard (*sigh*).
Regards,
Stuart
== 7 of 7 ==
Date: Thurs, Jan 9 2014 1:54 pm
From: Wouter van Ooijen
> IMHO, the obvious solution would be to use a programming language that
> takes care of such messy conversions, like Ada95. Ada lets you define
> fixed point numbers type so that the actual computation will be done
> through integer arithmetic. Ada has a real type system even for
> primitive types like int and float, not the C typedef crap. I wish that
> this would exist for C++, too, but I'm afraid that such a feature will
> never make it into the C++ standard (*sigh*).
It doesn't need to, C++ allows you to define such types yourself.
Wouter
==============================================================================
You received this message because you are subscribed to the Google Groups "comp.lang.c++"
group.
To post to this group, visit http://groups.google.com/group/comp.lang.c++?hl=en
To unsubscribe from this group, send email to comp.lang.c+++unsubscribe@googlegroups.com
To change the way you get mail from this group, visit:
http://groups.google.com/group/comp.lang.c++/subscribe?hl=en
To report abuse, send email explaining the problem to abuse@googlegroups.com
==============================================================================
Google Groups: http://groups.google.com/?hl=en
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment