bug# 16785. r: dp, valeski, neeti. Send mimetype info from channel to imglib.

If no decoder, sniff data stream for mime info.
This commit is contained in:
pnunn%netscape.com 1999-10-19 21:49:20 +00:00
parent 9436a61696
commit caab8220a0
7 changed files with 164 additions and 106 deletions

View File

@ -28,12 +28,14 @@
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsWeakPtr.h"
#include "prprf.h"
#include "nsITimer.h"
#include "nsVoidArray.h"
#include "nsString.h"
#include "prmem.h"
#include "plstr.h"
#include "il_strm.h"
//#include "il_strm.h"
#include "merrors.h"
#include "nsNeckoUtil.h"
@ -163,13 +165,32 @@ ImageConsumer::OnStartRequest(nsIChannel* channel, nsISupports* aContext)
return NS_ERROR_ABORT;
}
ilINetReader *reader = mURL->GetReader();
if (reader->StreamCreated(mURL, IL_UNKNOWN) != PR_TRUE) {
ilINetReader *reader = mURL->GetReader(); //ptn test: nsCOMPtr??
nsresult rv = NS_OK;
char* aContentType = NULL;
rv = channel->GetContentType(&aContentType); //nsCRT alloc's str
if (NS_FAILED(rv)) {
if(aContentType){
nsCRT::free(aContentType);
}
aContentType = nsCRT::strdup("unknown");
}
if(nsCRT::strlen(aContentType) > 50){
//somethings wrong. mimetype string shouldn't be this big.
//protect us from the user.
nsCRT::free(aContentType);
aContentType = nsCRT::strdup("unknown");
}
if (reader->StreamCreated(mURL, aContentType) != PR_TRUE) {
mStatus = MK_IMAGE_LOSSAGE;
reader->StreamAbort(mStatus);
NS_RELEASE(reader);
nsCRT::free(aContentType);
return NS_ERROR_ABORT;
}
nsCRT::free(aContentType);
NS_RELEASE(reader);
return NS_OK;
@ -192,7 +213,7 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn
NS_RELEASE(reader);
return NS_ERROR_ABORT;
}
nsresult err = 0;
PRUint32 nb;
@ -234,7 +255,7 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn
bytes_read += nb;
if (mFirstRead == PR_TRUE) {
err = reader->FirstWrite((const unsigned char *)mBuffer, nb);
err = reader->FirstWrite((const unsigned char *)mBuffer, nb );
mFirstRead = PR_FALSE; //? move after err chk?
/*
* If FirstWrite(...) fails then the image type
@ -253,7 +274,7 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn
if(NS_FAILED(err)){
mStatus = MK_IMAGE_LOSSAGE;
mInterrupted = PR_TRUE;
NS_RELEASE(reader);
NS_RELEASE(reader);
return NS_ERROR_ABORT;
}
} while(bytes_read < length);
@ -276,7 +297,6 @@ ImageConsumer::OnDataAvailable(nsIChannel* channel, nsISupports* aContext, nsIIn
} else {
NS_IF_RELEASE(mStream);
}
NS_RELEASE(reader);
return NS_OK;
}

View File

@ -25,7 +25,7 @@
#include "nsIURL.h"
#include "prmem.h"
#include "plstr.h"
#include "il_strm.h"
//#include "il_strm.h"
#ifndef NECKO
#include "nsINetService.h"
@ -199,8 +199,10 @@ ImageNetContextSyncImpl::GetURL(ilIURL* aURL,
#ifndef NECKO
// Initiate a synchronous URL load
if (NS_SUCCEEDED(service->OpenBlockingStream(url, nsnull, &stream)) &&
(aReader->StreamCreated(aURL, IL_UNKNOWN) == PR_TRUE)) {
(aReader->StreamCreated(aURL, "unknown") == PR_TRUE)) {
#else
nsIURI *uri = nsnull;
@ -212,13 +214,30 @@ ImageNetContextSyncImpl::GetURL(ilIURL* aURL,
nsIChannel *channel = nsnull;
rv = service->NewChannelFromURI("load", uri, nsnull, nsnull, &channel);
NS_RELEASE(uri);
if (NS_FAILED(rv)) return -1;
if (NS_FAILED(rv))
return -1;
char* aContentType = NULL;
rv = channel->GetContentType(&aContentType); //nsCRT alloc's str
if (NS_FAILED(rv)) {
if(aContentType){
nsCRT::free(aContentType);
}
aContentType = nsCRT::strdup("unknown");
}
if(nsCRT::strlen(aContentType) > 50){
//somethings wrong. mimetype string shouldn't be this big.
//protect us from the user.
nsCRT::free(aContentType);
aContentType = nsCRT::strdup("unknown");
}
rv = channel->OpenInputStream(0, -1, &stream);
NS_RELEASE(channel);
if (NS_FAILED(rv)) return -1;
if (NS_FAILED(rv))
return -1;
if (aReader->StreamCreated(aURL, IL_UNKNOWN) == PR_TRUE) {
if (aReader->StreamCreated(aURL, aContentType) == PR_TRUE) {
#endif // NECKO
@ -263,12 +282,15 @@ ImageNetContextSyncImpl::GetURL(ilIURL* aURL,
}
NS_IF_RELEASE(stream);
nsCRT::free(aContentType);
} else {
aReader->StreamAbort(-1);
status = -1;
}
aReader->NetRequestDone(aURL, status);
NS_IF_RELEASE(url);
return 0;

View File

@ -46,7 +46,7 @@ public:
NS_IMETHOD NetRequestDone(ilIURL *urls, int status)=0;
virtual PRBool StreamCreated(ilIURL *urls, int type)=0;
virtual PRBool StreamCreated(ilIURL *urls, char* type)=0;
virtual PRBool IsMulti()=0;
};

View File

@ -30,8 +30,9 @@
#include "xpcompat.h"
#include "prtypes.h"
#include "prprf.h"
#include "il_strm.h"
//#include "il_strm.h"
PR_BEGIN_EXTERN_C
@ -75,7 +76,7 @@ NS_IMETHODIMP ImgDCallbk::ImgDCBResetPalette()
if( ilContainer != NULL ) {
il_reset_palette(ilContainer);
}
return NS_OK;
return 0;
}
@ -197,24 +198,14 @@ ImgDCallbk :: ImgDCBClearTimeout(void *timer_id)
static void
il_description_notify(il_container *ic)
{
char buf[36], buf2[12];
char buf[36];
IL_MessageData message_data;
IL_ImageReq *image_req;
NI_PixmapHeader *img_header = &ic->image->header;
XP_BZERO(&message_data, sizeof(IL_MessageData));
switch (ic->type) {
/* XXX - This needs to be fixed for Image Plugins. */
case IL_GIF : PL_strcpy(buf2, "GIF"); break;
case IL_XBM : PL_strcpy(buf2, "XBM"); break;
case IL_JPEG : PL_strcpy(buf2, "JPEG"); break;
case IL_PNG : PL_strcpy(buf2, "PNG"); break;
case IL_ART : PL_strcpy(buf2, "ART"); break;
default : PL_strcpy(buf2, "");
}
XP_SPRINTF(buf, XP_GetString(XP_MSG_IMAGE_PIXELS), buf2,
XP_SPRINTF(buf, XP_GetString(XP_MSG_IMAGE_PIXELS), ic->type,
img_header->width, img_header->height);
PR_ASSERT(ic->clients);
@ -379,9 +370,9 @@ il_progress_notify(il_container *ic)
/* Could be zero if before il_size() is called. */
if (img_header->height == 0)
return;
int ret;
/* Interlaced GIFs are weird */
if (ic->type == IL_GIF) {
if (ret= nsCRT::strncasecmp(ic->type, "image/gif", 9) == 0) {
percent_done = il_compute_percentage_complete(row, ic);
}
else
@ -427,8 +418,8 @@ il_cache_return_notify(IL_ImageReq *image_req)
PR_ASSERT(ic->state >= IC_SIZED);
/* First notify observers of the image dimensions. */
message_data.width = ic->dest_width; /* Note: these are stored as */
message_data.height = ic->dest_height; /* uint16s. */
message_data.width = (unsigned short) ic->dest_width; /* Note: these are stored as */
message_data.height = (unsigned short) ic->dest_height; /* uint16s. */
XP_NotifyObservers(image_req->obs_list, IL_DIMENSIONS, &message_data);
message_data.width = message_data.height = 0;
@ -864,14 +855,15 @@ IL_StreamWriteReady(il_container *ic)
}
/* Given the first few bytes of a stream, identify the image format */
static int
il_type(int suspected_type, const char *buf, int32 len)
bool
sniffout_mimetype(const char *buf, int32 len, char* aContentType)
{
int i;
if (len >= 4 && !strncmp(buf, "GIF8", 4))
if (len >= 4 && !nsCRT::strncmp(buf, "GIF8", 4))
{
return IL_GIF;
PR_snprintf(aContentType, 10,"%s", "image/gif");
return TRUE;
}
/* for PNG */
@ -880,7 +872,8 @@ il_type(int suspected_type, const char *buf, int32 len)
(unsigned char)buf[2]==0x4E &&
(unsigned char)buf[3]==0x47))
{
return IL_PNG;
PR_snprintf(aContentType, 10,"%s","image/png");
return TRUE;
}
@ -895,8 +888,9 @@ il_type(int suspected_type, const char *buf, int32 len)
((unsigned char)buf[1])==0xD8 &&
((unsigned char)buf[2])==0xFF)
{
return IL_JPEG;
}
PR_snprintf(aContentType, 11,"%s", "image/jpeg");
return TRUE;
}
/* ART begins with JG (4A 47). Major version offset 2.
Minor version offset 3. Offset 4 must be NULL.
@ -906,7 +900,8 @@ il_type(int suspected_type, const char *buf, int32 len)
((unsigned char) buf[1])==0x47 &&
((unsigned char) buf[4])==0x00 )
{
return IL_ART;
PR_snprintf(aContentType, 10,"%s", "image/art");
return TRUE;
}
@ -914,35 +909,44 @@ il_type(int suspected_type, const char *buf, int32 len)
if (len >= 8 && !strncmp(buf, "#define ", 8) )
{
/* Don't contradict the given type, since this ID isn't definitive */
if ((suspected_type == IL_UNKNOWN) || (suspected_type == IL_XBM))
return IL_XBM;
PR_snprintf(aContentType, 8,"%s", "unknown");
return TRUE;
}
if (len < 35)
if (len < 12)
{
ILTRACE(1,("il: too few bytes to determine type"));
return suspected_type;
PR_snprintf(aContentType, 8,"%s", "unknown");
return FALSE;
}
/* all the servers return different formats so root around */
for (i=0; i<28; i++)
{
if (!strncmp(&buf[i], "Not Fou", 7))
return IL_NOTFOUND;
if (!strncmp(&buf[i], "Not Fou", 7)){
PR_snprintf(aContentType, 8,"%s", "unknown");
return FALSE;
}
}
return suspected_type;
//just in case
PR_snprintf(aContentType, 8,"%s", "unknown");
return FALSE;
}
/*
* determine what kind of image data we are dealing with
*/
IL_IMPLEMENT(int)
IL_Type(const char *buf, int32 len)
{
return il_type(IL_UNKNOWN, buf, len);
char aContent[200];
return sniffout_mimetype(buf, len, aContent);
}
int
IL_StreamWrite(il_container *ic, const unsigned char *str, int32 len)
{
@ -984,7 +988,7 @@ IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len)
PR_ASSERT(ic);
PR_ASSERT(ic->image);
/* If URL redirection occurs, the url stored in the
image container is the redirect url not the image file url.
If the image is animated, the imglib will never match the
@ -992,6 +996,7 @@ IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len)
ic->fetch_url keeps the actual url for you.
*/
FREE_IF_NOT_NULL(ic->fetch_url);
#ifdef NECKO
@ -1010,47 +1015,55 @@ IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len)
ic->fetch_url = NULL;
}
/* Figure out the image type, possibly overriding the given MIME type */
ic->type = il_type(ic->type, (const char*) str, len);
/* Grab the URL's expiration date */
if (ic->url)
ic->expires = ic->url->GetExpires();
nsIImgDecoder *imgdec;
char imgtype[150];
nsIImgDecoder *imgdec ;
char imgtypestr[200];
switch (ic->type) {
case IL_GIF : PL_strcpy(imgtype, "gif"); break;
case IL_XBM : PL_strcpy(imgtype, "xbm"); break;
case IL_JPEG : PL_strcpy(imgtype, "jpeg"); break;
case IL_PNG : PL_strcpy(imgtype, "png"); break;
case IL_ART : PL_strcpy(imgtype, "art"); break;
default : PL_strcpy(imgtype, "");
}
sprintf(imgtypestr, "component://netscape/image/decoder&type=image/%s"
, imgtype );
PR_snprintf(imgtypestr, sizeof(imgtypestr), "component://netscape/image/decoder&type=%s"
, ic->type );
static NS_DEFINE_IID(kIImgDecoderIID, NS_IIMGDECODER_IID);
rv = nsComponentManager::CreateInstance(imgtypestr, NULL,
kIImgDecoderIID, // XXX was previously kImgDecoderIID
(void **)&imgdec);
kIImgDecoderIID,
(void **)&imgdec);
if (NS_FAILED(rv))
return MK_IMAGE_LOSSAGE;
/* If no mimetype to decoder mapping, try to sniff out
the mime-type */
if (NS_FAILED(rv)){
char contenttype[50];
if(sniffout_mimetype((const char*) str, len, contenttype)){
/* try again with the guessed mimetype */
PR_snprintf(imgtypestr, sizeof(imgtypestr), "component://netscape/image/decoder&type=%s"
, contenttype );
rv = nsComponentManager::CreateInstance(imgtypestr, NULL,
kIImgDecoderIID, (void **)&imgdec);
}
if (NS_FAILED(rv))
/* we did our best. Gotta give up. */
return MK_IMAGE_LOSSAGE;
/*we found it*/
nsCRT::free(ic->type);
ic->type = NULL;
ic->type = nsCRT::strdup(contenttype);
}
imgdec->SetContainer(ic);
ic->imgdec = imgdec;
rv = imgdec->ImgDInit();
if(NS_FAILED(rv))
{
if(NS_FAILED(rv)){
NS_RELEASE(ic->imgdec);
ic->imgdec = nsnull;
ILTRACE(0,("il: image init failed"));
return MK_OUT_OF_MEMORY;
}
@ -1103,7 +1116,9 @@ il_bad_container(il_container *ic)
IL_ImageReq *image_req;
ILTRACE(4,("il: bad container, sending icon"));
if (ic->type == IL_NOTFOUND) {
if((ic->type)&&
((nsCRT::strlen(ic->type) < 8) ||
(nsCRT::strncmp(ic->type, "unknown", 7)==0))) {
ic->state = IC_MISSING;
for (image_req = ic->clients; image_req; image_req = image_req->next)
il_icon_notify(image_req, IL_IMAGE_NOT_FOUND, IL_ERROR_NO_DATA);
@ -1235,7 +1250,10 @@ IL_StreamComplete(il_container *ic, PRBool is_multipart)
#endif /* DEBUG */
PR_ASSERT(ic);
if(ic->type){
nsCRT::free(ic->type);
ic->type = NULL;
}
#ifdef DEBUG
cur_time = PR_Now();
LL_SUB(cur_time, cur_time, ic->start_time);
@ -1549,6 +1567,11 @@ IL_StreamAbort(il_container *ic, int status)
/* Abort the image. */
il_image_abort(ic);
if(ic->type){
nsCRT::free(ic->type);
ic->type = NULL;
}
if(ic->state >= IC_SIZED || (ic->state == IC_ABORT_PENDING)){
if (status == MK_INTERRUPTED){
@ -1581,7 +1604,7 @@ IL_StreamAbort(il_container *ic, int status)
PRBool
IL_StreamCreated(il_container *ic,
ilIURL *url,
int type)
char* type)
{
PR_ASSERT(ic);
@ -1592,14 +1615,14 @@ IL_StreamCreated(il_container *ic,
if (ic->state == IC_ABORT_PENDING)
return PR_FALSE;
ic->type = (int)type;
ic->type = nsCRT::strdup(type); //mime string
ic->content_length = url->GetContentLength();
#ifdef NECKO
char* addr = url->GetAddress();
ILTRACE(4,("il: new stream, type %d, %s", ic->type, addr));
ILTRACE(4,("il: new stream, type %s, %s", ic->type, addr));
nsCRT::free(addr);
#else
ILTRACE(4,("il: new stream, type %d, %s", ic->type,
ILTRACE(4,("il: new stream, type %s, %s", ic->type,
url->GetAddress()));
#endif
ic->state = IC_STREAM;

View File

@ -18,7 +18,7 @@
/* if.h --- Top-level image library internal routines
*
* $Id: if.h,v 3.10 1999/09/25 19:59:42 kipp%netscape.com Exp $
* $Id: if.h,v 3.11 1999/10/19 21:48:03 pnunn%netscape.com Exp $
*/
#ifndef _if_h
@ -207,7 +207,7 @@ struct il_container_struct {
IL_Pixmap *image; /* Destination image pixmap structure. */
IL_Pixmap *mask; /* Destination mask pixmap structure. */
intn type;
char* type; /* mimetype string ptn 10.13.99*/
void *ds; /* decoder's private data */
il_converter converter;
@ -364,32 +364,21 @@ extern PRBool il_image_stopped(il_container *ic);
extern ilINetReader *IL_NewNetReader(il_container *ic);
extern il_container *IL_GetNetReaderContainer(ilINetReader *reader);
#ifndef M12N_NEW_DEPENDENCIES /* XXXM12N */
extern int IL_StreamWriteReady(il_container *ic);
extern int IL_StreamFirstWrite(il_container *ic, const unsigned char *str, int32 len);
extern int IL_StreamWrite(il_container *ic, const unsigned char *str, int32 len);
extern void IL_StreamAbort(il_container *ic, int status);
extern void IL_StreamComplete(il_container *ic, PRBool is_multipart);
extern void IL_NetRequestDone(il_container *ic, ilIURL *urls, int status);
extern PRBool IL_StreamCreated(il_container *ic, ilIURL *urls, int type);
#else
extern jint
il_write_ready(NET_StreamClass *stream, jint op, struct JMCException* *exceptionThrown);
extern jint
il_first_write(NET_StreamClass *stream, jint op, jbyte* str, jsize len,
struct JMCException* *exceptionThrown);
extern void
il_abort(NET_StreamClass *stream, jint op, jint status,
struct JMCException* *exceptionThrown);
extern void
il_stream_complete(NET_StreamClass *stream, jint op,
struct JMCException* *exceptionThrown);
#endif /* M12N_NEW_DEPENDENCIES */
extern PRBool IL_StreamCreated(il_container *ic, ilIURL *urls, char* type);
#if 0
extern int il_xbm_init(il_container *ic);
extern int il_xbm_write(il_container *, const uint8 *, int32);
extern void il_xbm_complete(il_container *ic);
extern void il_xbm_abort(il_container *ic);
#endif
/* Allocate and initialize the destination image's transparent_pixel with
the Image Library's preferred transparency color i.e. the background color

View File

@ -41,7 +41,7 @@ public:
NS_IMETHOD NetRequestDone(ilIURL *urls, int status);
virtual PRBool StreamCreated(ilIURL *urls, int type);
virtual PRBool StreamCreated(ilIURL *urls, char* type);
virtual PRBool IsMulti();
@ -133,7 +133,7 @@ NetReaderImpl::NetRequestDone(ilIURL *urls, int status)
}
PRBool
NetReaderImpl::StreamCreated(ilIURL *urls, int type)
NetReaderImpl::StreamCreated(ilIURL *urls, char* type)
{
if (ilContainer != NULL) {
return IL_StreamCreated(ilContainer, urls, type);

View File

@ -24,8 +24,8 @@
#include "if.h" /* Image library internal declarations */
#include "il.h" /* Image library external API */
#include "il_strm.h" /* For image types. */
#include "prmem.h"
#include "nsCRT.h"
#include "nsVoidArray.h"
#include "nsITimer.h"
@ -971,8 +971,8 @@ il_emit_row(
drow_start * mask_header->widthBytes;
#endif
/* We know this mask is prescaled: */
if (ic->type == IL_ART){
/* We know this mask is prescaled: */
if (nsCRT::strncasecmp(ic->type, "image/art",9)==0){
/* No scaling needed*/
if (len == column_count)
XP_MEMCPY(maskp, cbuf, mask_header->widthBytes);
@ -1178,16 +1178,20 @@ il_emit_row(
dup = row_count - 1;
offset = dcolumn_start * (img_color_space->pixmap_depth / 8);
#ifndef M12N /* Clean this up */
if (ic->image->pixmap_depth == 1)
do_dither = TRUE;
else
do_dither = ic->converter && (row_count <= 4) &&
((ic->dither_mode == IL_Dither) || (ic->type == IL_JPEG));
((ic->dither_mode == IL_Dither) ||
(nsCRT::strncasecmp(ic->type, "image/jpeg",10)==0);
#else
do_dither = (ic->dither_mode == IL_Dither);
if ((ic->type == IL_GIF)||(ic->type == IL_PNG) && (!ic->converter || (row_count > 4)))
do_dither = FALSE;
if ((nsCRT::strncasecmp(ic->type, "image/gif",9)==0)||
(nsCRT::strncasecmp(ic->type, "image/png",9)==0) &&
(!ic->converter || (row_count > 4)))
do_dither = FALSE;
#endif /* M12N */