/*******************************************************************************
* Copyright (c) 2009, Adobe Systems Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* · Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* · Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* · Neither the name of Adobe Systems Incorporated nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
package com.adobe.dp.epub.util;
public class ImageDimensions {
private static int readInt(byte[] buf, int offset) {
return ((buf[offset] & 0xFF) << 24) | ((buf[offset + 1] & 0xFF) << 16) | ((buf[offset + 2] & 0xFF) << 8)
| (buf[offset + 3] & 0xFF);
}
private static int readShort(byte[] buf, int offset) {
return ((buf[offset] & 0xFF) << 8) | (buf[offset + 1] & 0xFF);
}
private static int readShortBE(byte[] buf, int offset) {
return (buf[offset] & 0xFF) | ((buf[offset + 1] & 0xFF) << 8);
}
public static int[] getImageDimensions(byte[] buf) {
if (buf[0] == (byte) 0xFF && buf[1] == (byte) 0xD8 && buf[2] == (byte) 0xFF && buf[3] == (byte) 0xE0
&& buf[6] == 'J' && buf[7] == 'F' && buf[8] == 'I' && buf[9] == 'F') {
// JPEG image
int k = 2;
while (k + 5 < buf.length && buf[k] == (byte) 0xFF) {
int tag = buf[k + 1] & 0xFF;
switch (tag) {
case 0xC0:
case 0xC1:
case 0xC2:
case 0xC3:
case 0xC9:
case 0xCA:
case 0xCB: {
int[] dim = new int[2];
dim[0] = readShort(buf, k + 7);
dim[1] = readShort(buf, k + 5);
return dim;
}
}
int size = 2 + ((buf[k + 2] & 0xFF) << 8) + (buf[k + 3] & 0xFF);
k += size;
}
} else if (buf[0] == 'G' && buf[1] == 'I' && buf[2] == 'F') {
// GIF image
int[] dim = new int[2];
dim[0] = readShortBE(buf, 6);
dim[1] = readShortBE(buf, 8);
return dim;
} else if (buf[0] == (byte) 0x89 && buf[1] == 'P' && buf[2] == 'N' && buf[3] == 'G' && buf[4] == 0x0D
&& buf[5] == 0x0A && buf[6] == 0x1A && buf[7] == 0x0A && buf[12] == 'I' && buf[13] == 'H'
&& buf[14] == 'D' && buf[15] == 'R') {
// PNG image
int[] dim = new int[2];
dim[0] = readInt(buf, 16);
dim[1] = readInt(buf, 20);
return dim;
}
return null;
}
/*
bool GetImageSize(const char *fn, int *x,int *y)
{ FILE *f=fopen(fn,"rb"); if (f==0) return false;
fseek(f,0,SEEK_END); long len=ftell(f); fseek(f,0,SEEK_SET);
if (len<24) {fclose(f); return false;}
// Strategy:
// reading GIF dimensions requires the first 10 bytes of the file
// reading PNG dimensions requires the first 24 bytes of the file
// reading JPEG dimensions requires scanning through jpeg chunks
// In all formats, the file is at least 24 bytes big, so we'll read that always
unsigned char buf[24]; fread(buf,1,24,f);
// For JPEGs, we need to read the first 12 bytes of each chunk.
// We'll read those 12 bytes at buf+2...buf+14, i.e. overwriting the existing buf.
if (buf[0]==0xFF && buf[1]==0xD8 && buf[2]==0xFF && buf[3]==0xE0 && buf[6]=='J' && buf[7]=='F' && buf[8]=='I' && buf[9]=='F')
{ long pos=2;
while (buf[2]==0xFF)
{ if (buf[3]==0xC0 || buf[3]==0xC1 || buf[3]==0xC2 || buf[3]==0xC3 || buf[3]==0xC9 || buf[3]==0xCA || buf[3]==0xCB) break;
pos += 2+(buf[4]<<8)+buf[5];
if (pos+12>len) break;
fseek(f,pos,SEEK_SET); fread(buf+2,1,12,f);
}
}
fclose(f);
// JPEG: (first two bytes of buf are first two bytes of the jpeg file; rest of buf is the DCT frame
if (buf[0]==0xFF && buf[1]==0xD8 && buf[2]==0xFF)
{ *y = (buf[7]<<8) + buf[8];
*x = (buf[9]<<8) + buf[10];
return true;
}
// GIF: first three bytes say "GIF", next three give version number. Then dimensions
if (buf[0]=='G' && buf[1]=='I' && buf[2]=='F')
{ *x = buf[6] + (buf[7]<<8);
*y = buf[8] + (buf[9]<<8);
return true;
}
// PNG: the first frame is by definition an IHDR frame, which gives dimensions
if ( buf[0]==0x89 && buf[1]=='P' && buf[2]=='N' && buf[3]=='G' && buf[4]==0x0D && buf[5]==0x0A && buf[6]==0x1A && buf[7]==0x0A
&& buf[12]=='I' && buf[13]=='H' && buf[14]=='D' && buf[15]=='R')
{ *x = (buf[16]<<24) + (buf[17]<<16) + (buf[18]<<8) + (buf[19]<<0);
*y = (buf[20]<<24) + (buf[21]<<16) + (buf[22]<<8) + (buf[23]<<0);
return true;
}
return false;
}
*/
}