Implementation of a TIM2 coder (#1571)

* Added ScaleColor4to8 and converse functions

* Implementation mostly done

* Build setup

* reordered processing of clut and pixels

* Added support for Shuffled CLUTs

* Revert "Added ScaleColor4to8 and converse functions"

This reverts commit b0bd8a59cc.

* Added more exceptions thrown when header is incorrect

* created enums and compacted rgb read functions

* Added alpha channel and changed alpha scaling

* Added support for format_type==1

* New define for assigning clut colors

* Changed names to avoid namespace conflicts

* Fixed alpha channel of RGB24 encoding

* Incorporated sanity check into the switch
This commit is contained in:
Ramiro Balado
2019-07-13 15:25:38 +02:00
committed by ImageMagick
parent c8ab8d9b32
commit 602ee2c216
8 changed files with 794 additions and 1 deletions
+2
View File
@@ -169,6 +169,7 @@ extern ModuleExport size_t
RegisterTIFFImage(void),
RegisterTILEImage(void),
RegisterTIMImage(void),
RegisterTIM2Image(void),
RegisterTTFImage(void),
RegisterTXTImage(void),
RegisterUILImage(void),
@@ -334,6 +335,7 @@ extern ModuleExport void
UnregisterTIFFImage(void),
UnregisterTILEImage(void),
UnregisterTIMImage(void),
UnregisterTIM2Image(void),
UnregisterTTFImage(void),
UnregisterTXTImage(void),
UnregisterUILImage(void),
+2 -1
View File
@@ -121,6 +121,7 @@ $call Make thumbnail.c
$call Make tiff.c
$call Make tile.c
$call Make tim.c
$call Make tim2.c
$call Make ttf.c
$call Make txt.c
$call Make uil.c
@@ -155,7 +156,7 @@ $library/create libCoders.olb aai,art,avs,bgr,bmp,braille,clip,clipboard,cip, -
jnx,json,hdr,label,cals,caption,palm,mac,magick,map,mat,matte,pango,rgf, -
meta,miff,mpc,mpr,msl,mpeg,mono,mtv,mvg,null,otb,pattern,pcd,pcl,pcx,pdb, -
pdf,pes,pict,pix,plasma,png,pnm,preview,ps,ps2,ps3,psd,pwp,raw,rgb,rla,rle, -
sct,sfw,sgi,stegano,sun,svg,tga,thumbnail,tiff,tile,tim,ttf,txt,uil,url, -
sct,sfw,sgi,stegano,sun,svg,tga,thumbnail,tiff,tile,tim,tim2,ttf,txt,uil,url, -
uyvy,vicar,vid,viff,wbmp,webp,wmf,wpg,x,xbm,xc,xcf,xpm,xps,xwd,ycbcr,yuv, -
mask,screenshot,vips,sixel,xtrn, -
cin,magick,scr,[-.magickcore]compress,[-.magickcore]prervicccm
+9
View File
@@ -190,6 +190,7 @@ MAGICKCORE_CODER_SRCS = \
coders/thumbnail.c \
coders/tile.c \
coders/tim.c \
coders/tim2.c \
coders/ttf.c \
coders/txt.c \
coders/uil.c \
@@ -338,6 +339,7 @@ CODERS_NOINST_HDRS = \
coders/tiff.h \
coders/tile.h \
coders/tim.h \
coders/tim2.h \
coders/ttf.h \
coders/txt.h \
coders/uil.h \
@@ -455,6 +457,7 @@ coders_LTLIBRARIES = \
coders/thumbnail.la \
coders/tile.la \
coders/tim.la \
coders/tim2.la \
coders/ttf.la \
coders/txt.la \
coders/uil.la \
@@ -1123,6 +1126,12 @@ coders_tim_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
coders_tim_la_LDFLAGS = $(MODULECOMMONFLAGS)
coders_tim_la_LIBADD = $(MAGICKCORE_LIBS)
# TIM2 coder module
coders_tim2_la_SOURCES = coders/tim2.c
coders_tim2_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
coders_tim2_la_LDFLAGS = $(MODULECOMMONFLAGS)
coders_tim2_la_LIBADD = $(MAGICKCORE_LIBS)
# TTF coder module
coders_ttf_la_SOURCES = coders/ttf.c
coders_ttf_la_CPPFLAGS = $(MAGICK_CODER_CPPFLAGS)
+1
View File
@@ -150,6 +150,7 @@ AddMagickCoder(THUMBNAIL)
#endif
AddMagickCoder(TILE)
AddMagickCoder(TIM)
AddMagickCoder(TIM2)
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
AddMagickCoder(TTF)
#endif
+1
View File
@@ -153,6 +153,7 @@
#endif
#include "coders/tile.h"
#include "coders/tim.h"
#include "coders/tim2.h"
#if defined(MAGICKCORE_FREETYPE_DELEGATE)
#include "coders/ttf.h"
#endif
+746
View File
@@ -0,0 +1,746 @@
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% TTTTT IIIII M M 222 %
% T I MM MM 2 2 %
% T I M M M 2 %
% T I M M 2 %
% T IIIII M M 22222 %
% %
% %
% Read PSX TIM2 Image Format %
% %
% Software Design %
% Ramiro Balado Ordax %
% May 2019 %
% %
% %
% Copyright 2019-2019 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
% obtain a copy of the License at %
% %
% https://imagemagick.org/script/license.php %
% %
% Unless required by applicable law or agreed to in writing, software %
% distributed under the License is distributed on an "AS IS" BASIS, %
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
% See the License for the specific language governing permissions and %
% limitations under the License. %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
*/
/*
Include declarations.
*/
#include "MagickCore/studio.h"
#include "MagickCore/blob.h"
#include "MagickCore/blob-private.h"
#include "MagickCore/cache.h"
#include "MagickCore/colormap.h"
#include "MagickCore/channel.h"
#include "MagickCore/exception.h"
#include "MagickCore/exception-private.h"
#include "MagickCore/image.h"
#include "MagickCore/image-private.h"
#include "MagickCore/list.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/monitor.h"
#include "MagickCore/monitor-private.h"
#include "MagickCore/pixel-accessor.h"
#include "MagickCore/quantum-private.h"
#include "MagickCore/static.h"
#include "MagickCore/string_.h"
#include "MagickCore/module.h"
/*
Typedef declarations
*/
typedef struct _TIM2FileHeader
{
uint32_t
magic_num;
uint8_t
format_vers,
format_type;
uint16_t
image_count;
char
reserved[8];
} TIM2FileHeader;
typedef struct _TIM2ImageHeader
{
uint32_t
total_size,
clut_size,
image_size;
uint16_t
header_size,
clut_color_count;
uint8_t
img_format,
mipmap_count,
clut_type,
bpp_type;
uint16_t
width,
height;
uint64_t
GsTex0,
GsTex1;
uint32_t
GsRegs,
GsTexClut;
} TIM2ImageHeader;
enum CSM {
CSM1=0,
CSM2=1,
};
enum TIM2ColorEncoding{
RGBA32=0,
RGB24=1,
RGBA16=2,
};
enum TIM2IndexEncoding{
IDTEX8=3,
IDTEX4=4,
};
/*
Static functions
*/
static inline TIM2ImageHeader ReadTIM2ImageHeader(Image *image)
{
TIM2ImageHeader
tim2_image_header;
tim2_image_header.total_size =ReadBlobLSBLong(image);
tim2_image_header.clut_size =ReadBlobLSBLong(image);
tim2_image_header.image_size =ReadBlobLSBLong(image);
tim2_image_header.header_size=ReadBlobLSBShort(image);
tim2_image_header.clut_color_count=ReadBlobLSBShort(image);
tim2_image_header.img_format =ReadBlobByte(image);
tim2_image_header.mipmap_count=ReadBlobByte(image);
tim2_image_header.clut_type =ReadBlobByte(image);
tim2_image_header.bpp_type =ReadBlobByte(image);
tim2_image_header.width =ReadBlobLSBShort(image);
tim2_image_header.height=ReadBlobLSBShort(image);
tim2_image_header.GsTex0=ReadBlobMSBLongLong(image);
tim2_image_header.GsTex1=ReadBlobMSBLongLong(image);
tim2_image_header.GsRegs =ReadBlobMSBLong(image);
tim2_image_header.GsTexClut=ReadBlobMSBLong(image);
return tim2_image_header;
}
static inline Quantum GetChannelValue(uint32_t word,uint8_t channel, enum TIM2ColorEncoding ce){
switch(ce)
{
case RGBA16:
// Documentation specifies padding with zeros for converting from 5 to 8 bits.
return ScaleCharToQuantum((word>>channel*5 & ~(~0x0<<5))<<3);
case RGB24:
case RGBA32:
return ScaleCharToQuantum(word>>channel*8 & ~(~0x0<<8));
default:
return -1;
}
}
static inline Quantum GetAlpha(uint32_t word, enum TIM2ColorEncoding ce){
switch(ce)
{
case RGBA16:
return ScaleCharToQuantum((word>>3*5&0x1F)==0?0:0xFF);
case RGBA32:
#ifndef MIN
#define MIN(a,b) ((a)<(b)? a:b)
#endif
// 0x80 -> 1.0 alpha. Multiply by 2 and clamp to 0xFF
return ScaleCharToQuantum(MIN((word>>3*8&0xFF)<<1,0xFF));
default:
return 0xFF;
}
}
static inline void deshufflePalette(Image *image,PixelInfo* oldColormap){
const uint8_t
pages=image->colors/32,//Pages per CLUT
blocks=4,//Blocks per page
colors=8;//Colors per block
size_t
i=0;
(void) memcpy(oldColormap,image->colormap,(size_t)image->colors*sizeof(*oldColormap));
/*
* Swap the 2nd and 3rd block in each page
*/
for(int page=0; page<pages; page++){
memcpy(&(image->colormap[i+1*colors]),&(oldColormap[i+2*colors]),colors*sizeof(PixelInfo));
memcpy(&(image->colormap[i+2*colors]),&(oldColormap[i+1*colors]),colors*sizeof(PixelInfo));
i+=blocks*colors;
}
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% R e a d T I M 2 I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% ReadTIM2Image() reads a PS2 TIM image file and returns it. It
% allocates the memory necessary for the new Image structure and returns a
% pointer to the new image.
%
% The format of the ReadTIM2Image method is:
%
% Image *ReadTIM2Image(const ImageInfo *image_info,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o image_info: the image info.
%
% o exception: return any errors or warnings in this structure.
%
*/
static Image *ReadTIM2Image(const ImageInfo *image_info, ExceptionInfo *exception)
{
TIM2FileHeader
tim2_file_header;
Image
*image;
MagickBooleanType
status;
ssize_t
count,
str_read;
/*
* Open image file.
*/
assert(image_info != (const ImageInfo *) NULL);
assert(image_info->signature == MagickCoreSignature);
if (image_info->debug != MagickFalse)
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image_info->filename);
assert(exception != (ExceptionInfo *) NULL);
assert(exception->signature == MagickCoreSignature);
image=AcquireImage(image_info,exception);
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
{
image=DestroyImageList(image);
return((Image *) NULL);
}
/*
* Verify TIM2 magic number.
*/
tim2_file_header.magic_num=ReadBlobMSBLong(image);
if (tim2_file_header.magic_num != 0x54494D32) /*"TIM2"*/
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
/*
* #### Read File Header ####
*/
tim2_file_header.format_vers=ReadBlobByte(image);
if(tim2_file_header.format_vers!=0x04)
ThrowReaderException(CoderError,"ImageTypeNotSupported");
tim2_file_header.format_type=ReadBlobByte(image);
tim2_file_header.image_count=ReadBlobLSBShort(image);
ReadBlobStream(image,8,&(tim2_file_header.reserved),&str_read);
/*
* Jump to first image header
*/
switch(tim2_file_header.format_type)
{
case 0x00:
SeekBlob(image,16,SEEK_SET);break;
case 0x01:
SeekBlob(image,128,SEEK_SET);break;
default:
ThrowReaderException(CoderError,"ImageTypeNotSupported");
}
/*
* Process each image. Only one image supported for now
*/
if(tim2_file_header.image_count!=1)
ThrowReaderException(CoderError,"NumberOfImagesIsNotSupported");
for(int i=0;i<tim2_file_header.image_count;++i)
{
TIM2ImageHeader
tim2_image_header;
MagickOffsetType ImgDataOffset=TellBlob(image);
enum CSM csm;
char
clut_depth=0,
has_clut=0,
bits_per_pixel=0;
/*
* #### Read Image Header ####
*/
tim2_image_header=ReadTIM2ImageHeader(image);
/*
* ### Process Image Header ###
*/
if(tim2_image_header.mipmap_count!=1)
ThrowReaderException(CoderError,"NumberOfImagesIsNotSupported");
image->columns=tim2_image_header.width;
image->rows=tim2_image_header.height;
has_clut=tim2_image_header.clut_type!=0;
if(has_clut){
// CLUT bits per color
switch((int) tim2_image_header.clut_type&0x0F)//Low 4 bits
{
case 1: clut_depth=16;break;
case 2: clut_depth=24;break;
case 3: clut_depth=32;break;
default:
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
break;
}
}
// Bits per pixel.
switch ((int) tim2_image_header.bpp_type)
{
case 1: bits_per_pixel=16;break;
case 2: bits_per_pixel=24;break;
case 3: bits_per_pixel=32;break;
case 4: bits_per_pixel=4;break;// Implies CLUT
case 5: bits_per_pixel=8;break;// Implies CLUT
default:
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
break;
}
image->depth=has_clut?clut_depth:bits_per_pixel;
if(image->depth==16 || image->depth==32)
SetImageAlphaChannel(image,ActivateAlphaChannel,exception);
else
SetImageAlphaChannel(image,OffAlphaChannel,exception);
SeekBlob(image,ImgDataOffset,SEEK_SET);
SeekBlob(image,tim2_image_header.header_size,SEEK_CUR);
{
/*
* ### Read Image Data ###
*/
unsigned char
*tim2_image_data;
size_t
bits_per_line,
bytes_per_line,
y;
register ssize_t
x;
register Quantum
*q;
register unsigned char
*p;
tim2_image_data=(unsigned char*) AcquireMagickMemory(tim2_image_header.image_size);
if (tim2_image_data == (unsigned char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
count=ReadBlob(image,tim2_image_header.image_size,tim2_image_data);
if (count!=(ssize_t)tim2_image_header.image_size)
{
tim2_image_data=(unsigned char *) RelinquishMagickMemory(tim2_image_data);
ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
}
/*
* ### Process Image Data ###
*/
status=SetImageExtent(image,image->columns,image->rows,exception);
if (status == MagickFalse)
return(DestroyImageList(image));
status=ResetImagePixels(image,exception);
if (status == MagickFalse)
return(DestroyImageList(image));
p=tim2_image_data;
bits_per_line=image->columns*bits_per_pixel;
bytes_per_line=bits_per_line/8 + ((bits_per_line%8==0)?0:1);
if(has_clut)
{
#define SyncNewPixels(image,exception,y) \
if(SyncAuthenticPixels(image,exception) == MagickFalse) break; \
if(image->previous == (Image *) NULL) \
{ \
status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,image->rows); \
if(status == MagickFalse) break; \
}
image->colors=tim2_image_header.clut_color_count;
if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
switch (bits_per_pixel)
{
case 4:
{
for (y=0; y<(ssize_t) image->rows; y++)
{
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
p=tim2_image_data+y*bytes_per_line;
for (x=0; x < ((ssize_t) image->columns-1); x+=2)
{
SetPixelIndex(image,(*p >> 0) & 0x0F,q);
q+=GetPixelChannels(image);
SetPixelIndex(image,(*p >> 4) & 0x0F,q);
p++;
q+=GetPixelChannels(image);
}
if ((image->columns % 2) != 0)
{
SetPixelIndex(image,(*p >> 4) & 0x0F,q);
p++;
q+=GetPixelChannels(image);
}
SyncNewPixels(image,exception,y);
}
break;
}
case 8:
{
for (y=0;y<(ssize_t) image->rows; y++)
{
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
p=tim2_image_data+y*bytes_per_line;
for (x=0; x < (ssize_t) image->columns; x++)
{
SetPixelIndex(image,*p,q);
p++;
q+=GetPixelChannels(image);
}
SyncNewPixels(image,exception,y);
}
break;
}
}
}
else //has_clut==false
{
#define SetPixelAllChannels(image,word,q,enc) \
SetPixelRed (image,GetChannelValue(word,0,enc),q); \
SetPixelGreen(image,GetChannelValue(word,1,enc),q); \
SetPixelBlue (image,GetChannelValue(word,2,enc),q);
uint32_t word;
switch (bits_per_pixel)
{
case 16:
{
for (y=0; y<(ssize_t) image->rows; y++)
{
p=tim2_image_data+y*bytes_per_line;
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
word = ((uint32_t)* p )<<0*8 |
((uint32_t)*(p+1))<<1*8;
SetPixelAllChannels(image,word,q,RGBA16);
SetPixelAlpha(image,GetAlpha(word,RGBA16),q);
q+=GetPixelChannels(image);
p+=sizeof(uint16_t);
}
SyncNewPixels(image,exception,y);
}
break;
}
case 24:
{
for (y = 0; y<(ssize_t) image->rows; y++)
{
p=tim2_image_data+y*bytes_per_line;
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
word = (uint32_t)(* p )<<0*8 |
(uint32_t)(*(p+1))<<1*8 |
(uint32_t)(*(p+2))<<2*8;
SetPixelAllChannels(image,word,q,RGB24);
q+=GetPixelChannels(image);
p+=3;
}
SyncNewPixels(image,exception,y);
}
break;
}
case 32:
{
for (y = 0; y<(ssize_t) image->rows; y++)
{
p=tim2_image_data+y*bytes_per_line;
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
for (x=0; x < (ssize_t) image->columns; x++)
{
word = ((uint32_t)* p )<<0*8 |
((uint32_t)*(p+1))<<1*8 |
((uint32_t)*(p+2))<<2*8 |
((uint32_t)*(p+3))<<3*8;
SetPixelAllChannels(image,word,q,RGBA32);
SetPixelAlpha(image,GetAlpha(word,RGBA32),q);
q+=GetPixelChannels(image);
p+=4;
}
SyncNewPixels(image,exception,y);
}
break;
}
default:
{
tim2_image_data=(unsigned char *) RelinquishMagickMemory(tim2_image_data);
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
}
}
}
tim2_image_data=(unsigned char *) RelinquishMagickMemory(tim2_image_data);
}
if (has_clut)
{
/*
* ### Read CLUT Data ###
*/
unsigned char
*tim2_clut_data;
register unsigned char
*p;
tim2_clut_data=(unsigned char *) AcquireMagickMemory(tim2_image_header.clut_size);
if (tim2_clut_data == (unsigned char *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
count=ReadBlob(image,tim2_image_header.clut_size,tim2_clut_data);
if (count != (ssize_t) (tim2_image_header.clut_size))
{
tim2_clut_data=(unsigned char *) RelinquishMagickMemory(tim2_clut_data);
ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
}
/*
* ### Process CLUT Data ###
*/
{
uint32_t word;
p=tim2_clut_data;
#define AssignAllChannels(image,word,enc) \
image->colormap[i].red =GetChannelValue(word,0,enc);\
image->colormap[i].green=GetChannelValue(word,1,enc);\
image->colormap[i].blue =GetChannelValue(word,2,enc);
switch(clut_depth)
{
case 16:
{
for (i=0;i<(ssize_t)image->colors;i++){
word = ((uint16_t)* p )<<0*8 |
((uint16_t)*(p+1))<<1*8;
AssignAllChannels(image,word,RGBA16);
image->colormap[i].alpha=GetAlpha(word,16);
p+=2;
}
break;
}
case 24:
{
for (i=0;i<(ssize_t)image->colors;i++){
word = ((uint32_t)* p )<<0*8 |
((uint32_t)*(p+1))<<1*8 |
((uint32_t)*(p+2))<<2*8;
AssignAllChannels(image,word,RGB24);
p+=3;
}
break;
}
case 32:
{
for (i=0;i<(ssize_t)image->colors;i++){
word = ((uint32_t)* p )<<0*8 |
((uint32_t)*(p+1))<<1*8 |
((uint32_t)*(p+2))<<2*8 |
((uint32_t)*(p+3))<<3*8;
AssignAllChannels(image,word,RGBA32);
image->colormap[i].alpha=GetAlpha(word,RGBA32);
p+=4;
}
break;
}
}
}
tim2_clut_data=(unsigned char *) RelinquishMagickMemory(tim2_clut_data);
//CSM: CLUT Storage Mode
switch ((int) tim2_image_header.clut_type>>4)//High 4 bits
{
case 0: csm=CSM1;break;
case 1: csm=CSM2;break;
default:
ThrowReaderException(CorruptImageError,"ImproperImageHeader");
break;
}
if(csm==CSM1){
PixelInfo *oldColormap=(PixelInfo *)AcquireQuantumMemory((size_t)(image->colors)+1,sizeof(*image->colormap));
if (oldColormap == (PixelInfo *) NULL)
ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
deshufflePalette(image,oldColormap);
RelinquishMagickMemory(oldColormap);
}
}
if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
if (image->scene >= (image_info->scene+image_info->number_scenes-1))
break;
if (image->storage_class == PseudoClass)
if (EOFBlob(image) != MagickFalse)
{
ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
image->filename);
break;
}
/*
Proceed to next image.
*/
if (image_info->number_scenes != 0)
if (image->scene >= (image_info->scene+image_info->number_scenes-1))
break;
}
(void) CloseBlob(image);
if (status == MagickFalse)
return(DestroyImageList(image));
return(GetFirstImageInList(image));
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% R e g i s t e r T I M 2 I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% RegisterTIM2Image() adds attributes for the TIM2 image format to
% the list of supported formats. The attributes include the image format
% tag, a method to read and/or write the format, whether the format
% supports the saving of more than one frame to the same file or blob,
% whether the format supports native in-memory I/O, and a brief
% description of the format.
%
% The format of the RegisterTIM2Image method is:
%
% size_t RegisterTIM2Image(void)
%
*/
ModuleExport size_t RegisterTIM2Image(void)
{
MagickInfo
*entry;
entry=AcquireMagickInfo("TIM2","TM2","PS2 TIM2");
entry->decoder=(DecodeImageHandler *) ReadTIM2Image;
(void) RegisterMagickInfo(entry);
return(MagickImageCoderSignature);
}
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% %
% %
% U n r e g i s t e r T I M 2 I m a g e %
% %
% %
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% UnregisterTIM2Image() removes format registrations made by the
% TIM2 module from the list of supported formats.
%
% The format of the UnregisterTIM2Image method is:
%
% UnregisterTIM2Image(void)
%
*/
ModuleExport void UnregisterTIM2Image(void)
{
(void) UnregisterMagickInfo("TM2");
}
+32
View File
@@ -0,0 +1,32 @@
/*
Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization
dedicated to making software imaging solutions freely available.
You may not use this file except in compliance with the License. You may
obtain a copy of the License at
https://imagemagick.org/script/license.php
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "coders/coders-private.h"
#define MagickTIM2Headers
#define MagickTIM2Aliases \
MagickCoderAlias("TIM2","TM2")
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
MagickCoderExports(TIM2)
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
+1
View File
@@ -347,6 +347,7 @@ static const struct ReferenceFormats
{ "TIFF64", UndefinedCompression, 0.0 },
{ "TILE", UndefinedCompression, 0.0 },
{ "TIM", UndefinedCompression, 0.0 },
{ "TIM2", UndefinedCompression, 0.0 },
{ "TTC", UndefinedCompression, 0.0 },
{ "TTF", UndefinedCompression, 0.0 },
{ "TXT", UndefinedCompression, 0.0 },